@mindexec/cli 0.2.6 → 0.2.8
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/README.md +12 -0
- package/package.json +1 -1
- package/remote-hub.js +167 -0
- package/scripts/remote-hub-smoke.mjs +54 -0
- package/server.js +28 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +366 -15
- package/wwwroot/_framework/MindExecution.Core.pnw79cgqjx.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.79mgmkpsy1.dll → MindExecution.Kernel.dt3w864bqn.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.8ey1m70q79.dll → MindExecution.Plugins.Admin.z93cu32xru.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.8rvwgqzxaz.dll → MindExecution.Plugins.Business.b6da8sg85t.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.ynnk3bqf03.dll → MindExecution.Plugins.Concept.mjooiqft9j.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.vi24rmnuyq.dll → MindExecution.Plugins.Directory.rjod6rdmly.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.9r08m5atjr.dll → MindExecution.Plugins.PlanMaster.1dcrzhsegj.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.fjkbniwa4o.dll → MindExecution.Plugins.YouTube.k75qxhbpp8.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.e0qnm5vtax.dll → MindExecution.Shared.y3eqxd3mvo.dll} +0 -0
- package/wwwroot/_framework/MindExecution.Web.wou9x6mn2f.dll +0 -0
- package/wwwroot/_framework/blazor.boot.json +21 -21
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +24 -24
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/MindExecution.Core.kf4752v5yl.dll +0 -0
- package/wwwroot/_framework/MindExecution.Web.wk9yv02eva.dll +0 -0
package/README.md
CHANGED
|
@@ -83,6 +83,18 @@ curl -X POST -H "X-Bridge-Token: <bridge-token>" http://127.0.0.1:5147/api/remot
|
|
|
83
83
|
curl -H "X-Bridge-Token: <bridge-token>" http://127.0.0.1:5147/api/remote/devices/<device-id>/thumbnail
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
Start, read, and stop the focused view-only RemoteFast live stream:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
curl -X POST -H "X-Bridge-Token: <bridge-token>" -H "Content-Type: application/json" \
|
|
90
|
+
-d "{\"fps\":12,\"maxWidth\":960,\"maxHeight\":540,\"quality\":60}" \
|
|
91
|
+
http://127.0.0.1:5147/api/remote/devices/<device-id>/live/start
|
|
92
|
+
|
|
93
|
+
curl -H "X-Bridge-Token: <bridge-token>" http://127.0.0.1:5147/api/remote/devices/<device-id>/live/frame
|
|
94
|
+
|
|
95
|
+
curl -X POST -H "X-Bridge-Token: <bridge-token>" http://127.0.0.1:5147/api/remote/devices/<device-id>/live/stop
|
|
96
|
+
```
|
|
97
|
+
|
|
86
98
|
Queue a safe task-only instruction for one device or all connected devices:
|
|
87
99
|
|
|
88
100
|
```bash
|
package/package.json
CHANGED
package/remote-hub.js
CHANGED
|
@@ -7,6 +7,7 @@ const DEFAULT_REMOTE_HUB_HOST = '127.0.0.1';
|
|
|
7
7
|
const DEFAULT_HEARTBEAT_MS = 5000;
|
|
8
8
|
const MAX_LINE_CHARS = 4 * 1024 * 1024;
|
|
9
9
|
const MAX_THUMBNAIL_BASE64_CHARS = 3 * 1024 * 1024;
|
|
10
|
+
const MAX_STREAM_BASE64_CHARS = 3 * 1024 * 1024;
|
|
10
11
|
const MAX_AGENT_TASK_CHARS = 4000;
|
|
11
12
|
const MAX_AGENT_TASK_RESULT_CHARS = 3000;
|
|
12
13
|
const RECENT_TASK_LIMIT = 12;
|
|
@@ -118,6 +119,8 @@ function serializeDevice(device) {
|
|
|
118
119
|
remoteAddress: device.remoteAddress,
|
|
119
120
|
remotePort: device.remotePort,
|
|
120
121
|
latestThumbnail: device.latestThumbnail ? { ...device.latestThumbnail } : null,
|
|
122
|
+
latestLiveFrame: device.latestLiveFrame ? { ...device.latestLiveFrame } : null,
|
|
123
|
+
activeLiveStream: device.activeLiveStream ? { ...device.activeLiveStream } : null,
|
|
121
124
|
latestTask: device.latestTask ? { ...device.latestTask } : null,
|
|
122
125
|
recentTasks: Array.isArray(device.recentTasks)
|
|
123
126
|
? device.recentTasks.map(task => ({ ...task }))
|
|
@@ -249,6 +252,8 @@ export function createRemoteHub(options = {}) {
|
|
|
249
252
|
remotePort: socket.remotePort || 0,
|
|
250
253
|
status: {},
|
|
251
254
|
latestThumbnail: null,
|
|
255
|
+
latestLiveFrame: null,
|
|
256
|
+
activeLiveStream: null,
|
|
252
257
|
latestTask: null,
|
|
253
258
|
recentTasks: [],
|
|
254
259
|
pendingTaskCommands: new Map(),
|
|
@@ -259,6 +264,10 @@ export function createRemoteHub(options = {}) {
|
|
|
259
264
|
commandResultsReceived: 0,
|
|
260
265
|
thumbnailFramesReceived: 0,
|
|
261
266
|
thumbnailFramesDropped: 0,
|
|
267
|
+
liveFramesReceived: 0,
|
|
268
|
+
liveFramesDropped: 0,
|
|
269
|
+
liveStreamsStarted: 0,
|
|
270
|
+
liveStreamsStopped: 0,
|
|
262
271
|
tasksQueued: 0,
|
|
263
272
|
taskResultsReceived: 0,
|
|
264
273
|
taskResultsFailed: 0
|
|
@@ -297,6 +306,11 @@ export function createRemoteHub(options = {}) {
|
|
|
297
306
|
device.socket = null;
|
|
298
307
|
device.disconnectedAt = new Date().toISOString();
|
|
299
308
|
device.lastDisconnectReason = reason;
|
|
309
|
+
if (device.activeLiveStream) {
|
|
310
|
+
device.activeLiveStream.active = false;
|
|
311
|
+
device.activeLiveStream.stoppedAt = device.disconnectedAt;
|
|
312
|
+
device.activeLiveStream.stopReason = reason;
|
|
313
|
+
}
|
|
300
314
|
logWarn('remote', `device disconnected ${device.deviceName} (${deviceId}): ${reason}`);
|
|
301
315
|
emitRemoteEvent('RemoteDeviceDisconnected', device, { reason });
|
|
302
316
|
}
|
|
@@ -475,6 +489,62 @@ export function createRemoteHub(options = {}) {
|
|
|
475
489
|
});
|
|
476
490
|
break;
|
|
477
491
|
}
|
|
492
|
+
case 'stream.frame': {
|
|
493
|
+
const frameData = safeString(message.data, MAX_STREAM_BASE64_CHARS + 1);
|
|
494
|
+
const frameSeq = Number(message.frameSeq);
|
|
495
|
+
const streamId = safeString(message.streamId, 128) || 'live';
|
|
496
|
+
if (!device.activeLiveStream?.active || device.activeLiveStream.streamId !== streamId) {
|
|
497
|
+
device.counters.liveFramesDropped += 1;
|
|
498
|
+
emitRemoteEvent('RemoteFrameDropped', device, {
|
|
499
|
+
reason: 'stale-live-stream-frame',
|
|
500
|
+
streamId,
|
|
501
|
+
frameSeq: Number.isFinite(frameSeq) ? frameSeq : null
|
|
502
|
+
});
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (!frameData || frameData.length > MAX_STREAM_BASE64_CHARS || !Number.isFinite(frameSeq)) {
|
|
507
|
+
device.counters.liveFramesDropped += 1;
|
|
508
|
+
emitRemoteEvent('RemoteFrameDropped', device, {
|
|
509
|
+
reason: 'invalid-live-frame',
|
|
510
|
+
streamId,
|
|
511
|
+
frameSeq: Number.isFinite(frameSeq) ? frameSeq : null
|
|
512
|
+
});
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const mimeType = safeString(message.mimeType || message.format || 'image/jpeg', 80) || 'image/jpeg';
|
|
517
|
+
const capturedAt = safeString(message.capturedAt, 80) || device.lastSeenAt;
|
|
518
|
+
device.latestLiveFrame = {
|
|
519
|
+
streamId,
|
|
520
|
+
frameSeq,
|
|
521
|
+
commandId: safeString(message.commandId, 128),
|
|
522
|
+
width: Number.isFinite(Number(message.width)) ? Number(message.width) : 0,
|
|
523
|
+
height: Number.isFinite(Number(message.height)) ? Number(message.height) : 0,
|
|
524
|
+
mimeType,
|
|
525
|
+
format: mimeType,
|
|
526
|
+
mode: safeString(message.mode || device.activeLiveStream.mode || 'remote-fast', 80),
|
|
527
|
+
fps: Number.isFinite(Number(message.fps)) ? Number(message.fps) : device.activeLiveStream.fps,
|
|
528
|
+
capturedAt,
|
|
529
|
+
receivedAt: device.lastSeenAt,
|
|
530
|
+
byteLength: Math.floor(frameData.length * 3 / 4),
|
|
531
|
+
dataUrl: frameData.startsWith('data:')
|
|
532
|
+
? frameData
|
|
533
|
+
: `data:${mimeType};base64,${frameData}`
|
|
534
|
+
};
|
|
535
|
+
device.activeLiveStream.lastFrameAt = device.lastSeenAt;
|
|
536
|
+
device.activeLiveStream.lastFrameSeq = frameSeq;
|
|
537
|
+
device.activeLiveStream.framesReceived = (device.activeLiveStream.framesReceived || 0) + 1;
|
|
538
|
+
device.counters.liveFramesReceived += 1;
|
|
539
|
+
emitRemoteEvent('RemoteFrameReceived', device, {
|
|
540
|
+
streamId,
|
|
541
|
+
frameSeq,
|
|
542
|
+
width: device.latestLiveFrame.width,
|
|
543
|
+
height: device.latestLiveFrame.height,
|
|
544
|
+
mode: device.latestLiveFrame.mode
|
|
545
|
+
});
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
478
548
|
default:
|
|
479
549
|
emitRemoteEvent('RemoteAgentMessageIgnored', device, {
|
|
480
550
|
messageType: safeString(message.type, 80)
|
|
@@ -731,6 +801,100 @@ export function createRemoteHub(options = {}) {
|
|
|
731
801
|
});
|
|
732
802
|
}
|
|
733
803
|
|
|
804
|
+
function startLiveStream(deviceId, options = {}) {
|
|
805
|
+
const device = devices.get(String(deviceId || ''));
|
|
806
|
+
if (!device?.socket || device.socket.destroyed || !device.connected) {
|
|
807
|
+
return { ok: false, error: 'device-not-connected' };
|
|
808
|
+
}
|
|
809
|
+
if (!readCapabilityFlag(device.capabilities, 'liveStream')) {
|
|
810
|
+
return { ok: false, error: 'device-live-stream-unavailable' };
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const now = new Date().toISOString();
|
|
814
|
+
const streamId = safeString(options.streamId, 128) || `live-${Date.now()}`;
|
|
815
|
+
const fps = clampNumber(options.fps, 1, 24, 12);
|
|
816
|
+
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
817
|
+
const result = sendCommand(deviceId, {
|
|
818
|
+
command: 'stream.start',
|
|
819
|
+
commandId,
|
|
820
|
+
payload: {
|
|
821
|
+
streamId,
|
|
822
|
+
mode: safeString(options.mode, 80) || 'remote-fast',
|
|
823
|
+
fps,
|
|
824
|
+
maxWidth: clampNumber(options.maxWidth, 320, 2560, 960),
|
|
825
|
+
maxHeight: clampNumber(options.maxHeight, 180, 1440, 540),
|
|
826
|
+
quality: clampNumber(options.quality, 20, 95, 60),
|
|
827
|
+
requestedAt: now
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
if (!result.ok) {
|
|
832
|
+
return result;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
device.activeLiveStream = {
|
|
836
|
+
streamId,
|
|
837
|
+
commandId,
|
|
838
|
+
active: true,
|
|
839
|
+
mode: 'remote-fast',
|
|
840
|
+
fps,
|
|
841
|
+
startedAt: now,
|
|
842
|
+
stoppedAt: '',
|
|
843
|
+
stopReason: '',
|
|
844
|
+
lastFrameAt: '',
|
|
845
|
+
lastFrameSeq: 0,
|
|
846
|
+
framesReceived: 0
|
|
847
|
+
};
|
|
848
|
+
device.counters.liveStreamsStarted += 1;
|
|
849
|
+
emitRemoteEvent('RemoteLiveStreamStarted', device, {
|
|
850
|
+
streamId,
|
|
851
|
+
commandId,
|
|
852
|
+
fps
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
return { ok: true, commandId, streamId, fps };
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
function stopLiveStream(deviceId, options = {}) {
|
|
859
|
+
const device = devices.get(String(deviceId || ''));
|
|
860
|
+
if (!device?.socket || device.socket.destroyed || !device.connected) {
|
|
861
|
+
return { ok: false, error: 'device-not-connected' };
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
const streamId = safeString(options.streamId, 128) || device.activeLiveStream?.streamId || '';
|
|
865
|
+
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
866
|
+
const result = sendCommand(deviceId, {
|
|
867
|
+
command: 'stream.stop',
|
|
868
|
+
commandId,
|
|
869
|
+
payload: {
|
|
870
|
+
streamId,
|
|
871
|
+
requestedAt: new Date().toISOString()
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
if (!result.ok) {
|
|
876
|
+
return result;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
if (device.activeLiveStream && (!streamId || device.activeLiveStream.streamId === streamId)) {
|
|
880
|
+
device.activeLiveStream.active = false;
|
|
881
|
+
device.activeLiveStream.stoppedAt = new Date().toISOString();
|
|
882
|
+
device.activeLiveStream.stopReason = 'manager-request';
|
|
883
|
+
}
|
|
884
|
+
device.counters.liveStreamsStopped += 1;
|
|
885
|
+
emitRemoteEvent('RemoteLiveStreamStopped', device, {
|
|
886
|
+
streamId,
|
|
887
|
+
commandId
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
return { ok: true, commandId, streamId };
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function getDeviceLiveFrame(deviceId) {
|
|
894
|
+
const device = devices.get(String(deviceId || ''));
|
|
895
|
+
return device?.latestLiveFrame ? { ...device.latestLiveFrame } : null;
|
|
896
|
+
}
|
|
897
|
+
|
|
734
898
|
function getDeviceThumbnail(deviceId) {
|
|
735
899
|
const device = devices.get(String(deviceId || ''));
|
|
736
900
|
return device?.latestThumbnail ? { ...device.latestThumbnail } : null;
|
|
@@ -745,6 +909,9 @@ export function createRemoteHub(options = {}) {
|
|
|
745
909
|
sendCommand,
|
|
746
910
|
requestAgentTask,
|
|
747
911
|
requestThumbnail,
|
|
912
|
+
startLiveStream,
|
|
913
|
+
stopLiveStream,
|
|
914
|
+
getDeviceLiveFrame,
|
|
748
915
|
getDeviceThumbnail,
|
|
749
916
|
getPairToken: () => pairToken
|
|
750
917
|
};
|
|
@@ -61,6 +61,7 @@ try {
|
|
|
61
61
|
status: true,
|
|
62
62
|
thumbnail: false,
|
|
63
63
|
control: false,
|
|
64
|
+
liveStream: true,
|
|
64
65
|
computerAgent: true,
|
|
65
66
|
taskDispatch: true,
|
|
66
67
|
aiAssist: true,
|
|
@@ -112,6 +113,59 @@ try {
|
|
|
112
113
|
assert.equal(thumbnailDevice.latestThumbnail.streamId, 'smoke-thumb');
|
|
113
114
|
assert.equal(thumbnailDevice.counters.thumbnailFramesReceived, 1);
|
|
114
115
|
|
|
116
|
+
const liveCommand = hub.startLiveStream('smoke-device', {
|
|
117
|
+
streamId: 'smoke-live',
|
|
118
|
+
fps: 5,
|
|
119
|
+
maxWidth: 320,
|
|
120
|
+
maxHeight: 180,
|
|
121
|
+
quality: 50
|
|
122
|
+
});
|
|
123
|
+
assert.equal(liveCommand.ok, true);
|
|
124
|
+
writeJsonLine(socket, {
|
|
125
|
+
type: 'stream.frame',
|
|
126
|
+
commandId: liveCommand.commandId,
|
|
127
|
+
streamId: 'smoke-live',
|
|
128
|
+
frameSeq: 2,
|
|
129
|
+
width: 2,
|
|
130
|
+
height: 1,
|
|
131
|
+
mimeType: 'image/png',
|
|
132
|
+
mode: 'remote-fast',
|
|
133
|
+
fps: 5,
|
|
134
|
+
capturedAt: new Date().toISOString(),
|
|
135
|
+
data: 'iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC'
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const liveDevice = await waitFor(() => {
|
|
139
|
+
const current = hub.listDevices();
|
|
140
|
+
return current[0]?.latestLiveFrame?.streamId === 'smoke-live' ? current[0] : null;
|
|
141
|
+
});
|
|
142
|
+
assert.equal(liveDevice.activeLiveStream.active, true);
|
|
143
|
+
assert.equal(liveDevice.latestLiveFrame.mode, 'remote-fast');
|
|
144
|
+
assert.equal(liveDevice.counters.liveFramesReceived, 1);
|
|
145
|
+
|
|
146
|
+
const staleFrameBefore = liveDevice.counters.liveFramesDropped;
|
|
147
|
+
writeJsonLine(socket, {
|
|
148
|
+
type: 'stream.frame',
|
|
149
|
+
streamId: 'stale-live',
|
|
150
|
+
frameSeq: 3,
|
|
151
|
+
width: 2,
|
|
152
|
+
height: 1,
|
|
153
|
+
mimeType: 'image/png',
|
|
154
|
+
capturedAt: new Date().toISOString(),
|
|
155
|
+
data: 'iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC'
|
|
156
|
+
});
|
|
157
|
+
const staleDropDevice = await waitFor(() => {
|
|
158
|
+
const current = hub.listDevices();
|
|
159
|
+
return current[0]?.counters?.liveFramesDropped > staleFrameBefore ? current[0] : null;
|
|
160
|
+
});
|
|
161
|
+
assert.equal(staleDropDevice.latestLiveFrame.streamId, 'smoke-live');
|
|
162
|
+
|
|
163
|
+
const stopLiveCommand = hub.stopLiveStream('smoke-device', {
|
|
164
|
+
streamId: 'smoke-live'
|
|
165
|
+
});
|
|
166
|
+
assert.equal(stopLiveCommand.ok, true);
|
|
167
|
+
assert.equal(hub.listDevices()[0].activeLiveStream.active, false);
|
|
168
|
+
|
|
115
169
|
const taskCommand = hub.requestAgentTask('smoke-device', {
|
|
116
170
|
instruction: 'Summarize current desktop status for the manager.',
|
|
117
171
|
title: 'Smoke task'
|
package/server.js
CHANGED
|
@@ -7048,6 +7048,34 @@ app.post('/api/remote/devices/:deviceId/thumbnail/request', (req, res) => {
|
|
|
7048
7048
|
}));
|
|
7049
7049
|
});
|
|
7050
7050
|
|
|
7051
|
+
app.get('/api/remote/devices/:deviceId/live/frame', (req, res) => {
|
|
7052
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
7053
|
+
const frame = remoteHub.getDeviceLiveFrame(req.params.deviceId);
|
|
7054
|
+
if (!frame) {
|
|
7055
|
+
res.status(404).json({ ok: false, error: 'live-frame-not-available' });
|
|
7056
|
+
return;
|
|
7057
|
+
}
|
|
7058
|
+
|
|
7059
|
+
res.json({ ok: true, frame });
|
|
7060
|
+
});
|
|
7061
|
+
|
|
7062
|
+
app.post('/api/remote/devices/:deviceId/live/start', (req, res) => {
|
|
7063
|
+
res.json(remoteHub.startLiveStream(req.params.deviceId, {
|
|
7064
|
+
streamId: req.body?.streamId,
|
|
7065
|
+
mode: req.body?.mode,
|
|
7066
|
+
fps: req.body?.fps,
|
|
7067
|
+
maxWidth: req.body?.maxWidth,
|
|
7068
|
+
maxHeight: req.body?.maxHeight,
|
|
7069
|
+
quality: req.body?.quality
|
|
7070
|
+
}));
|
|
7071
|
+
});
|
|
7072
|
+
|
|
7073
|
+
app.post('/api/remote/devices/:deviceId/live/stop', (req, res) => {
|
|
7074
|
+
res.json(remoteHub.stopLiveStream(req.params.deviceId, {
|
|
7075
|
+
streamId: req.body?.streamId
|
|
7076
|
+
}));
|
|
7077
|
+
});
|
|
7078
|
+
|
|
7051
7079
|
app.get('/api/codex/capabilities', async (req, res) => {
|
|
7052
7080
|
try {
|
|
7053
7081
|
res.json(await getCodexRuntime().getCapabilities());
|
|
@@ -12105,6 +12105,21 @@
|
|
|
12105
12105
|
return select;
|
|
12106
12106
|
}
|
|
12107
12107
|
|
|
12108
|
+
const REMOTE_FLEET_MONITOR_REFRESH_MS = 5000;
|
|
12109
|
+
const REMOTE_FLEET_LIVE_REFRESH_MS = 1000;
|
|
12110
|
+
|
|
12111
|
+
function clearRemoteFleetTimers(bodyView) {
|
|
12112
|
+
if (!bodyView) return;
|
|
12113
|
+
if (bodyView._remoteFleetLiveRefreshTimer) {
|
|
12114
|
+
clearInterval(bodyView._remoteFleetLiveRefreshTimer);
|
|
12115
|
+
bodyView._remoteFleetLiveRefreshTimer = null;
|
|
12116
|
+
}
|
|
12117
|
+
if (bodyView._remoteFleetMonitorRefreshTimer) {
|
|
12118
|
+
clearInterval(bodyView._remoteFleetMonitorRefreshTimer);
|
|
12119
|
+
bodyView._remoteFleetMonitorRefreshTimer = null;
|
|
12120
|
+
}
|
|
12121
|
+
}
|
|
12122
|
+
|
|
12108
12123
|
function getRemoteFleetDeviceField(device, camelKey, pascalKey, fallback = '') {
|
|
12109
12124
|
const value = device?.[camelKey] ?? device?.[pascalKey] ?? fallback;
|
|
12110
12125
|
return value === undefined || value === null ? fallback : value;
|
|
@@ -12139,6 +12154,19 @@
|
|
|
12139
12154
|
return /^data:image\/(png|jpe?g|webp|svg\+xml);base64,/i.test(dataUrl);
|
|
12140
12155
|
}
|
|
12141
12156
|
|
|
12157
|
+
function hasRemoteFleetLiveFrame(device) {
|
|
12158
|
+
const dataUrl = String(getRemoteFleetDeviceField(device, 'liveFrameDataUrl', 'LiveFrameDataUrl', ''));
|
|
12159
|
+
return /^data:image\/(png|jpe?g|webp|svg\+xml);base64,/i.test(dataUrl);
|
|
12160
|
+
}
|
|
12161
|
+
|
|
12162
|
+
function isRemoteFleetLiveActive(device) {
|
|
12163
|
+
return getRemoteFleetDeviceField(device, 'liveStreamActive', 'LiveStreamActive', false) === true;
|
|
12164
|
+
}
|
|
12165
|
+
|
|
12166
|
+
function isRemoteFleetThumbnailCapable(device) {
|
|
12167
|
+
return getRemoteFleetDeviceField(device, 'thumbnailEnabled', 'ThumbnailEnabled', false) === true;
|
|
12168
|
+
}
|
|
12169
|
+
|
|
12142
12170
|
function getRemoteFleetTimestampMs(value) {
|
|
12143
12171
|
const timestamp = Date.parse(String(value || ''));
|
|
12144
12172
|
return Number.isFinite(timestamp) ? timestamp : 0;
|
|
@@ -12165,6 +12193,8 @@
|
|
|
12165
12193
|
getRemoteFleetDeviceField(device, 'release', 'Release', ''),
|
|
12166
12194
|
getRemoteFleetDeviceField(device, 'arch', 'Arch', ''),
|
|
12167
12195
|
getRemoteFleetDeviceField(device, 'agentVersion', 'AgentVersion', ''),
|
|
12196
|
+
getRemoteFleetDeviceField(device, 'liveStreamMode', 'LiveStreamMode', ''),
|
|
12197
|
+
isRemoteFleetLiveActive(device) ? 'live active remote-fast' : '',
|
|
12168
12198
|
getRemoteFleetDeviceField(device, 'latestTaskTitle', 'LatestTaskTitle', ''),
|
|
12169
12199
|
getRemoteFleetDeviceField(device, 'latestTaskStatus', 'LatestTaskStatus', ''),
|
|
12170
12200
|
getRemoteFleetDeviceField(device, 'latestTaskResultSummary', 'LatestTaskResultSummary', ''),
|
|
@@ -12210,6 +12240,7 @@
|
|
|
12210
12240
|
|
|
12211
12241
|
function renderRemoteFleetMonitor(bodyView, nodeModel) {
|
|
12212
12242
|
if (!bodyView) return;
|
|
12243
|
+
clearRemoteFleetTimers(bodyView);
|
|
12213
12244
|
|
|
12214
12245
|
const nodeId = String(nodeModel?.id ?? nodeModel?.Id ?? '');
|
|
12215
12246
|
const searchState = bodyView.dataset.remoteFleetSearch || '';
|
|
@@ -12217,8 +12248,19 @@
|
|
|
12217
12248
|
const sortState = bodyView.dataset.remoteFleetSort || 'status';
|
|
12218
12249
|
const densityState = bodyView.dataset.remoteFleetDensity || 'cards';
|
|
12219
12250
|
const aiAssistState = bodyView.dataset.remoteFleetAiAssist === 'true';
|
|
12251
|
+
const autoMonitorState = bodyView.dataset.remoteFleetAutoMonitor !== 'false';
|
|
12252
|
+
const focusState = bodyView.dataset.remoteFleetFocusDeviceId || '';
|
|
12220
12253
|
const devices = [...parseRemoteFleetDevices(nodeModel)]
|
|
12221
12254
|
.sort((left, right) => compareRemoteFleetDevices(left, right, sortState));
|
|
12255
|
+
const hasActiveLiveStream = devices.some(isRemoteFleetLiveActive);
|
|
12256
|
+
const hasMonitorTargets = devices.some(device =>
|
|
12257
|
+
isRemoteFleetDeviceConnected(device) && isRemoteFleetThumbnailCapable(device));
|
|
12258
|
+
const focusedDevice = devices.find(device => getRemoteFleetDeviceId(device) === focusState)
|
|
12259
|
+
|| devices.find(device => isRemoteFleetLiveActive(device))
|
|
12260
|
+
|| null;
|
|
12261
|
+
if (focusedDevice) {
|
|
12262
|
+
bodyView.dataset.remoteFleetFocusDeviceId = getRemoteFleetDeviceId(focusedDevice);
|
|
12263
|
+
}
|
|
12222
12264
|
const total = Number(getRemoteFleetMetadataValue(nodeModel, 'RemoteFleetDeviceCount', devices.length));
|
|
12223
12265
|
const connected = Number(getRemoteFleetMetadataValue(
|
|
12224
12266
|
nodeModel,
|
|
@@ -12266,7 +12308,7 @@
|
|
|
12266
12308
|
const commandRow = document.createElement('div');
|
|
12267
12309
|
commandRow.style.cssText = `
|
|
12268
12310
|
display: grid;
|
|
12269
|
-
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
12311
|
+
grid-template-columns: minmax(0, 1fr) auto auto auto;
|
|
12270
12312
|
gap: 8px;
|
|
12271
12313
|
align-items: center;
|
|
12272
12314
|
flex: 0 0 auto;
|
|
@@ -12291,7 +12333,42 @@
|
|
|
12291
12333
|
|
|
12292
12334
|
const copyButton = createRemoteFleetButton('Copy', 'Copy agent command', 'copy-command');
|
|
12293
12335
|
const refreshButton = createRemoteFleetButton('Refresh', 'Refresh remote devices', 'refresh');
|
|
12336
|
+
const autoMonitorLabel = document.createElement('label');
|
|
12337
|
+
autoMonitorLabel.title = 'Refresh stale thumbnails on a bounded timer';
|
|
12338
|
+
autoMonitorLabel.style.cssText = `
|
|
12339
|
+
display: inline-flex;
|
|
12340
|
+
align-items: center;
|
|
12341
|
+
justify-content: center;
|
|
12342
|
+
gap: 6px;
|
|
12343
|
+
height: 34px;
|
|
12344
|
+
padding: 0 9px;
|
|
12345
|
+
border-radius: 7px;
|
|
12346
|
+
border: 1px solid rgba(14, 165, 233, 0.28);
|
|
12347
|
+
background: ${autoMonitorState ? 'rgba(240, 249, 255, 0.92)' : 'rgba(248, 250, 252, 0.92)'};
|
|
12348
|
+
color: ${autoMonitorState ? '#0369a1' : '#475569'};
|
|
12349
|
+
font-size: 11px;
|
|
12350
|
+
font-weight: 900;
|
|
12351
|
+
letter-spacing: 0;
|
|
12352
|
+
cursor: pointer;
|
|
12353
|
+
pointer-events: auto;
|
|
12354
|
+
user-select: none;
|
|
12355
|
+
`;
|
|
12356
|
+
const autoMonitorToggle = document.createElement('input');
|
|
12357
|
+
autoMonitorToggle.type = 'checkbox';
|
|
12358
|
+
autoMonitorToggle.checked = autoMonitorState;
|
|
12359
|
+
autoMonitorToggle.dataset.remoteFleetAutoToggle = 'true';
|
|
12360
|
+
autoMonitorToggle.style.cssText = `
|
|
12361
|
+
width: 14px;
|
|
12362
|
+
height: 14px;
|
|
12363
|
+
margin: 0;
|
|
12364
|
+
accent-color: #0284c7;
|
|
12365
|
+
`;
|
|
12366
|
+
const autoMonitorText = document.createElement('span');
|
|
12367
|
+
autoMonitorText.textContent = 'Auto';
|
|
12368
|
+
autoMonitorLabel.appendChild(autoMonitorToggle);
|
|
12369
|
+
autoMonitorLabel.appendChild(autoMonitorText);
|
|
12294
12370
|
commandRow.appendChild(commandText);
|
|
12371
|
+
commandRow.appendChild(autoMonitorLabel);
|
|
12295
12372
|
commandRow.appendChild(copyButton);
|
|
12296
12373
|
commandRow.appendChild(refreshButton);
|
|
12297
12374
|
bodyView.appendChild(commandRow);
|
|
@@ -12333,6 +12410,7 @@
|
|
|
12333
12410
|
{ value: 'offline', label: 'Offline' },
|
|
12334
12411
|
{ value: 'task', label: 'Task' },
|
|
12335
12412
|
{ value: 'ai', label: 'AI' },
|
|
12413
|
+
{ value: 'live', label: 'Live' },
|
|
12336
12414
|
{ value: 'frames', label: 'Frames' },
|
|
12337
12415
|
{ value: 'issues', label: 'Issues' }
|
|
12338
12416
|
], filterState, 'Device filter');
|
|
@@ -12465,6 +12543,141 @@
|
|
|
12465
12543
|
`;
|
|
12466
12544
|
bodyView.appendChild(taskFeedback);
|
|
12467
12545
|
|
|
12546
|
+
if (focusedDevice) {
|
|
12547
|
+
const focusedId = getRemoteFleetDeviceId(focusedDevice);
|
|
12548
|
+
const focusedName = getRemoteFleetDeviceName(focusedDevice);
|
|
12549
|
+
const liveActive = isRemoteFleetLiveActive(focusedDevice);
|
|
12550
|
+
const liveFrameDataUrl = String(getRemoteFleetDeviceField(focusedDevice, 'liveFrameDataUrl', 'LiveFrameDataUrl', ''));
|
|
12551
|
+
const liveFrameAt = String(getRemoteFleetDeviceField(focusedDevice, 'liveFrameReceivedAt', 'LiveFrameReceivedAt', ''));
|
|
12552
|
+
const liveStreamId = String(getRemoteFleetDeviceField(focusedDevice, 'liveStreamId', 'LiveStreamId', ''));
|
|
12553
|
+
const hasLiveFrame = hasRemoteFleetLiveFrame(focusedDevice);
|
|
12554
|
+
const livePanel = document.createElement('section');
|
|
12555
|
+
livePanel.dataset.remoteFleetLivePanel = 'true';
|
|
12556
|
+
livePanel.dataset.deviceId = focusedId;
|
|
12557
|
+
livePanel.style.cssText = `
|
|
12558
|
+
flex: 0 0 auto;
|
|
12559
|
+
display: grid;
|
|
12560
|
+
grid-template-columns: minmax(220px, 0.95fr) minmax(0, 1.25fr);
|
|
12561
|
+
gap: 10px;
|
|
12562
|
+
min-height: 170px;
|
|
12563
|
+
padding: 10px;
|
|
12564
|
+
border-radius: 8px;
|
|
12565
|
+
border: 1px solid rgba(14, 165, 233, 0.24);
|
|
12566
|
+
background: rgba(255, 255, 255, 0.82);
|
|
12567
|
+
`;
|
|
12568
|
+
|
|
12569
|
+
const livePreview = document.createElement('div');
|
|
12570
|
+
livePreview.style.cssText = `
|
|
12571
|
+
position: relative;
|
|
12572
|
+
min-width: 0;
|
|
12573
|
+
aspect-ratio: 16 / 9;
|
|
12574
|
+
overflow: hidden;
|
|
12575
|
+
border-radius: 7px;
|
|
12576
|
+
background: linear-gradient(135deg, #111827 0%, #1f2937 100%);
|
|
12577
|
+
border: 1px solid rgba(15, 23, 42, 0.16);
|
|
12578
|
+
`;
|
|
12579
|
+
if (hasLiveFrame) {
|
|
12580
|
+
const image = document.createElement('img');
|
|
12581
|
+
image.src = liveFrameDataUrl;
|
|
12582
|
+
image.alt = `${focusedName} live screen`;
|
|
12583
|
+
image.decoding = 'async';
|
|
12584
|
+
image.style.cssText = `
|
|
12585
|
+
width: 100%;
|
|
12586
|
+
height: 100%;
|
|
12587
|
+
object-fit: cover;
|
|
12588
|
+
display: block;
|
|
12589
|
+
`;
|
|
12590
|
+
livePreview.appendChild(image);
|
|
12591
|
+
} else {
|
|
12592
|
+
const placeholder = document.createElement('div');
|
|
12593
|
+
placeholder.textContent = liveActive ? 'Waiting for live frame' : 'Live view idle';
|
|
12594
|
+
placeholder.style.cssText = `
|
|
12595
|
+
position: absolute;
|
|
12596
|
+
inset: 0;
|
|
12597
|
+
display: flex;
|
|
12598
|
+
align-items: center;
|
|
12599
|
+
justify-content: center;
|
|
12600
|
+
color: rgba(226, 232, 240, 0.82);
|
|
12601
|
+
font-size: 12px;
|
|
12602
|
+
font-weight: 900;
|
|
12603
|
+
letter-spacing: 0;
|
|
12604
|
+
`;
|
|
12605
|
+
livePreview.appendChild(placeholder);
|
|
12606
|
+
}
|
|
12607
|
+
const liveBadge = document.createElement('span');
|
|
12608
|
+
liveBadge.textContent = liveActive
|
|
12609
|
+
? `LIVE ${liveFrameAt ? formatRemoteFleetAge(liveFrameAt) : ''}`.trim()
|
|
12610
|
+
: 'FOCUS';
|
|
12611
|
+
liveBadge.style.cssText = `
|
|
12612
|
+
position: absolute;
|
|
12613
|
+
left: 7px;
|
|
12614
|
+
top: 7px;
|
|
12615
|
+
max-width: calc(100% - 14px);
|
|
12616
|
+
padding: 4px 7px;
|
|
12617
|
+
border-radius: 999px;
|
|
12618
|
+
background: ${liveActive ? 'rgba(220, 38, 38, 0.86)' : 'rgba(15, 23, 42, 0.72)'};
|
|
12619
|
+
color: #ffffff;
|
|
12620
|
+
font-size: 9px;
|
|
12621
|
+
font-weight: 950;
|
|
12622
|
+
line-height: 1;
|
|
12623
|
+
overflow: hidden;
|
|
12624
|
+
text-overflow: ellipsis;
|
|
12625
|
+
white-space: nowrap;
|
|
12626
|
+
letter-spacing: 0;
|
|
12627
|
+
`;
|
|
12628
|
+
livePreview.appendChild(liveBadge);
|
|
12629
|
+
|
|
12630
|
+
const liveInfo = document.createElement('div');
|
|
12631
|
+
liveInfo.style.cssText = `
|
|
12632
|
+
min-width: 0;
|
|
12633
|
+
display: flex;
|
|
12634
|
+
flex-direction: column;
|
|
12635
|
+
justify-content: space-between;
|
|
12636
|
+
gap: 8px;
|
|
12637
|
+
`;
|
|
12638
|
+
const liveTitle = document.createElement('div');
|
|
12639
|
+
liveTitle.style.cssText = 'min-width:0;display:flex;flex-direction:column;gap:3px;';
|
|
12640
|
+
const liveName = document.createElement('strong');
|
|
12641
|
+
liveName.textContent = focusedName;
|
|
12642
|
+
liveName.title = focusedName;
|
|
12643
|
+
liveName.style.cssText = 'color:#0f172a;font-size:15px;font-weight:950;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
12644
|
+
const liveMeta = document.createElement('span');
|
|
12645
|
+
liveMeta.textContent = liveActive
|
|
12646
|
+
? `RemoteFast ${getRemoteFleetDeviceField(focusedDevice, 'liveStreamFps', 'LiveStreamFps', 0) || 12} fps`
|
|
12647
|
+
: 'View-only focused screen stream';
|
|
12648
|
+
liveMeta.style.cssText = 'color:#475569;font-size:11px;font-weight:800;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
12649
|
+
liveTitle.appendChild(liveName);
|
|
12650
|
+
liveTitle.appendChild(liveMeta);
|
|
12651
|
+
|
|
12652
|
+
const liveActions = document.createElement('div');
|
|
12653
|
+
liveActions.style.cssText = 'display:flex;align-items:center;gap:8px;flex-wrap:wrap;';
|
|
12654
|
+
if (isRemoteFleetDeviceConnected(focusedDevice) && getRemoteFleetDeviceField(focusedDevice, 'liveStreamEnabled', 'LiveStreamEnabled', false) === true) {
|
|
12655
|
+
const startLiveButton = createRemoteFleetButton(liveActive ? 'Restart live' : 'Start live', 'Start focused view-only live stream', 'live-start');
|
|
12656
|
+
startLiveButton.dataset.deviceId = focusedId;
|
|
12657
|
+
startLiveButton.style.height = '30px';
|
|
12658
|
+
liveActions.appendChild(startLiveButton);
|
|
12659
|
+
if (liveActive) {
|
|
12660
|
+
const stopLiveButton = createRemoteFleetButton('Stop live', 'Stop focused live stream', 'live-stop');
|
|
12661
|
+
stopLiveButton.dataset.deviceId = focusedId;
|
|
12662
|
+
stopLiveButton.dataset.streamId = liveStreamId;
|
|
12663
|
+
stopLiveButton.style.height = '30px';
|
|
12664
|
+
stopLiveButton.style.borderColor = 'rgba(220, 38, 38, 0.32)';
|
|
12665
|
+
stopLiveButton.style.color = '#b91c1c';
|
|
12666
|
+
liveActions.appendChild(stopLiveButton);
|
|
12667
|
+
}
|
|
12668
|
+
} else {
|
|
12669
|
+
const disabled = document.createElement('span');
|
|
12670
|
+
disabled.textContent = 'Live unavailable';
|
|
12671
|
+
disabled.style.cssText = 'color:#64748b;font-size:11px;font-weight:900;';
|
|
12672
|
+
liveActions.appendChild(disabled);
|
|
12673
|
+
}
|
|
12674
|
+
liveInfo.appendChild(liveTitle);
|
|
12675
|
+
liveInfo.appendChild(liveActions);
|
|
12676
|
+
livePanel.appendChild(livePreview);
|
|
12677
|
+
livePanel.appendChild(liveInfo);
|
|
12678
|
+
bodyView.appendChild(livePanel);
|
|
12679
|
+
}
|
|
12680
|
+
|
|
12468
12681
|
if (lastError.trim()) {
|
|
12469
12682
|
const errorEl = document.createElement('div');
|
|
12470
12683
|
errorEl.textContent = lastError;
|
|
@@ -12524,7 +12737,13 @@
|
|
|
12524
12737
|
const thumbnailEnabled = device?.thumbnailEnabled === true || device?.ThumbnailEnabled === true;
|
|
12525
12738
|
const thumbnailDataUrl = String(device?.thumbnailDataUrl || device?.ThumbnailDataUrl || '');
|
|
12526
12739
|
const thumbnailCapturedAt = String(device?.thumbnailCapturedAt || device?.ThumbnailCapturedAt || '');
|
|
12740
|
+
const liveStreamEnabled = device?.liveStreamEnabled === true || device?.LiveStreamEnabled === true;
|
|
12741
|
+
const liveStreamActive = isRemoteFleetLiveActive(device);
|
|
12742
|
+
const liveStreamId = String(device?.liveStreamId || device?.LiveStreamId || '');
|
|
12743
|
+
const liveFrameDataUrl = String(device?.liveFrameDataUrl || device?.LiveFrameDataUrl || '');
|
|
12744
|
+
const liveFrameReceivedAt = String(device?.liveFrameReceivedAt || device?.LiveFrameReceivedAt || '');
|
|
12527
12745
|
const hasThumbnail = hasRemoteFleetThumbnail(device);
|
|
12746
|
+
const hasLiveFrame = hasRemoteFleetLiveFrame(device);
|
|
12528
12747
|
const taskEnabled = isRemoteFleetDeviceTaskCapable(device);
|
|
12529
12748
|
const aiAssistEnabled = isRemoteFleetDeviceAiCapable(device);
|
|
12530
12749
|
const aiModel = String(device?.aiModel || device?.AiModel || '');
|
|
@@ -12540,7 +12759,9 @@
|
|
|
12540
12759
|
card.dataset.remoteFleetConnected = connectedDevice ? 'true' : 'false';
|
|
12541
12760
|
card.dataset.remoteFleetTaskCapable = taskEnabled ? 'true' : 'false';
|
|
12542
12761
|
card.dataset.remoteFleetAiCapable = aiAssistEnabled ? 'true' : 'false';
|
|
12543
|
-
card.dataset.remoteFleetHasFrame = hasThumbnail ? 'true' : 'false';
|
|
12762
|
+
card.dataset.remoteFleetHasFrame = (hasThumbnail || hasLiveFrame) ? 'true' : 'false';
|
|
12763
|
+
card.dataset.remoteFleetLiveCapable = liveStreamEnabled ? 'true' : 'false';
|
|
12764
|
+
card.dataset.remoteFleetLiveActive = liveStreamActive ? 'true' : 'false';
|
|
12544
12765
|
card.dataset.remoteFleetIssue = (!connectedDevice || latestTaskStatus === 'failed' || !!latestTaskError) ? 'true' : 'false';
|
|
12545
12766
|
card.style.cssText = `
|
|
12546
12767
|
display: flex;
|
|
@@ -12556,6 +12777,8 @@
|
|
|
12556
12777
|
`;
|
|
12557
12778
|
|
|
12558
12779
|
if (densityState !== 'dense') {
|
|
12780
|
+
const previewDataUrl = hasLiveFrame ? liveFrameDataUrl : thumbnailDataUrl;
|
|
12781
|
+
const previewAt = hasLiveFrame ? liveFrameReceivedAt : thumbnailCapturedAt;
|
|
12559
12782
|
const preview = document.createElement('div');
|
|
12560
12783
|
preview.style.cssText = `
|
|
12561
12784
|
position: relative;
|
|
@@ -12566,10 +12789,10 @@
|
|
|
12566
12789
|
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
12567
12790
|
border: 1px solid rgba(15, 23, 42, 0.12);
|
|
12568
12791
|
`;
|
|
12569
|
-
if (hasThumbnail) {
|
|
12792
|
+
if (hasLiveFrame || hasThumbnail) {
|
|
12570
12793
|
const image = document.createElement('img');
|
|
12571
|
-
image.src =
|
|
12572
|
-
image.alt = `${name} thumbnail`;
|
|
12794
|
+
image.src = previewDataUrl;
|
|
12795
|
+
image.alt = hasLiveFrame ? `${name} live frame` : `${name} thumbnail`;
|
|
12573
12796
|
image.loading = 'lazy';
|
|
12574
12797
|
image.decoding = 'async';
|
|
12575
12798
|
image.style.cssText = `
|
|
@@ -12595,9 +12818,11 @@
|
|
|
12595
12818
|
`;
|
|
12596
12819
|
preview.appendChild(placeholder);
|
|
12597
12820
|
}
|
|
12598
|
-
if (
|
|
12821
|
+
if (previewAt) {
|
|
12599
12822
|
const badge = document.createElement('span');
|
|
12600
|
-
badge.textContent =
|
|
12823
|
+
badge.textContent = hasLiveFrame
|
|
12824
|
+
? `LIVE ${formatRemoteFleetAge(previewAt)}`
|
|
12825
|
+
: formatRemoteFleetAge(previewAt);
|
|
12601
12826
|
badge.style.cssText = `
|
|
12602
12827
|
position: absolute;
|
|
12603
12828
|
right: 6px;
|
|
@@ -12605,7 +12830,7 @@
|
|
|
12605
12830
|
max-width: calc(100% - 12px);
|
|
12606
12831
|
padding: 3px 6px;
|
|
12607
12832
|
border-radius: 999px;
|
|
12608
|
-
background: rgba(15, 23, 42, 0.74);
|
|
12833
|
+
background: ${hasLiveFrame ? 'rgba(220, 38, 38, 0.82)' : 'rgba(15, 23, 42, 0.74)'};
|
|
12609
12834
|
color: #e2e8f0;
|
|
12610
12835
|
font-size: 9px;
|
|
12611
12836
|
font-weight: 900;
|
|
@@ -12763,11 +12988,11 @@
|
|
|
12763
12988
|
actions.style.cssText = 'display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:auto;';
|
|
12764
12989
|
const status = document.createElement('span');
|
|
12765
12990
|
status.textContent = connectedDevice
|
|
12766
|
-
? (aiAssistEnabled ? `AI ${aiModel || 'ready'}` : 'Connected')
|
|
12991
|
+
? (liveStreamActive ? 'Live' : (aiAssistEnabled ? `AI ${aiModel || 'ready'}` : 'Connected'))
|
|
12767
12992
|
: 'Offline';
|
|
12768
12993
|
status.style.cssText = `
|
|
12769
12994
|
min-width: 0;
|
|
12770
|
-
color: ${connectedDevice ? '#047857' : '#64748b'};
|
|
12995
|
+
color: ${liveStreamActive ? '#b91c1c' : (connectedDevice ? '#047857' : '#64748b')};
|
|
12771
12996
|
font-size: 11px;
|
|
12772
12997
|
font-weight: 900;
|
|
12773
12998
|
overflow: hidden;
|
|
@@ -12776,6 +13001,23 @@
|
|
|
12776
13001
|
`;
|
|
12777
13002
|
actions.appendChild(status);
|
|
12778
13003
|
if (connectedDevice && deviceId) {
|
|
13004
|
+
const focusButton = createRemoteFleetButton('Focus', 'Show this device in focused live panel', 'live-focus');
|
|
13005
|
+
focusButton.dataset.deviceId = deviceId;
|
|
13006
|
+
focusButton.style.height = '24px';
|
|
13007
|
+
focusButton.style.fontSize = '10px';
|
|
13008
|
+
actions.appendChild(focusButton);
|
|
13009
|
+
if (liveStreamEnabled) {
|
|
13010
|
+
const liveButton = createRemoteFleetButton(liveStreamActive ? 'Stop' : 'Live', liveStreamActive ? 'Stop live stream' : 'Start focused live stream', liveStreamActive ? 'live-stop' : 'live-start');
|
|
13011
|
+
liveButton.dataset.deviceId = deviceId;
|
|
13012
|
+
liveButton.dataset.streamId = liveStreamId;
|
|
13013
|
+
liveButton.style.height = '24px';
|
|
13014
|
+
liveButton.style.fontSize = '10px';
|
|
13015
|
+
if (liveStreamActive) {
|
|
13016
|
+
liveButton.style.borderColor = 'rgba(220, 38, 38, 0.32)';
|
|
13017
|
+
liveButton.style.color = '#b91c1c';
|
|
13018
|
+
}
|
|
13019
|
+
actions.appendChild(liveButton);
|
|
13020
|
+
}
|
|
12779
13021
|
if (taskEnabled) {
|
|
12780
13022
|
const taskButton = createRemoteFleetButton('Task', 'Dispatch task to this device', 'task-device');
|
|
12781
13023
|
taskButton.dataset.deviceId = deviceId;
|
|
@@ -12822,8 +13064,7 @@
|
|
|
12822
13064
|
bodyView.appendChild(grid);
|
|
12823
13065
|
|
|
12824
13066
|
const footer = document.createElement('div');
|
|
12825
|
-
footer.textContent = `Endpoint ${endpoint}
|
|
12826
|
-
footer.textContent = `Endpoint ${endpoint} - all devices, no paging - refreshed ${formatRemoteFleetAge(refreshedAt)}`;
|
|
13067
|
+
footer.textContent = `Endpoint ${endpoint} - all devices, no paging - ${autoMonitorState ? 'auto monitor' : 'manual'} - refreshed ${formatRemoteFleetAge(refreshedAt)}`;
|
|
12827
13068
|
footer.style.cssText = `
|
|
12828
13069
|
flex: 0 0 auto;
|
|
12829
13070
|
color: #64748b;
|
|
@@ -12860,6 +13101,20 @@
|
|
|
12860
13101
|
const readTaskInstruction = () => String(taskInput.value || '').trim();
|
|
12861
13102
|
const useAiAssist = () => aiToggle.checked === true;
|
|
12862
13103
|
const getDeviceCards = () => Array.from(grid.querySelectorAll('article[data-device-id]'));
|
|
13104
|
+
const refreshRemoteFleetNode = async () => {
|
|
13105
|
+
if (bodyView._remoteFleetRefreshInFlight === true) {
|
|
13106
|
+
return null;
|
|
13107
|
+
}
|
|
13108
|
+
|
|
13109
|
+
bodyView._remoteFleetRefreshInFlight = true;
|
|
13110
|
+
try {
|
|
13111
|
+
const result = await invokeDotNetAsync('RefreshRemoteFleetMonitorNodeFromJs', nodeId);
|
|
13112
|
+
await syncRemoteFleetNodeStateFromResult(result);
|
|
13113
|
+
return result;
|
|
13114
|
+
} finally {
|
|
13115
|
+
bodyView._remoteFleetRefreshInFlight = false;
|
|
13116
|
+
}
|
|
13117
|
+
};
|
|
12863
13118
|
const getVisibleEligibleDeviceIds = () => {
|
|
12864
13119
|
const wantsAi = useAiAssist();
|
|
12865
13120
|
return getDeviceCards()
|
|
@@ -12887,6 +13142,7 @@
|
|
|
12887
13142
|
|| (filterMode === 'offline' && card.dataset.remoteFleetConnected !== 'true')
|
|
12888
13143
|
|| (filterMode === 'task' && card.dataset.remoteFleetConnected === 'true' && card.dataset.remoteFleetTaskCapable === 'true')
|
|
12889
13144
|
|| (filterMode === 'ai' && card.dataset.remoteFleetConnected === 'true' && card.dataset.remoteFleetAiCapable === 'true')
|
|
13145
|
+
|| (filterMode === 'live' && card.dataset.remoteFleetLiveActive === 'true')
|
|
12890
13146
|
|| (filterMode === 'frames' && card.dataset.remoteFleetHasFrame === 'true')
|
|
12891
13147
|
|| (filterMode === 'issues' && card.dataset.remoteFleetIssue === 'true');
|
|
12892
13148
|
const show = matchesSearch && matchesMode;
|
|
@@ -12935,10 +13191,19 @@
|
|
|
12935
13191
|
control.addEventListener(eventName, event => event.stopPropagation());
|
|
12936
13192
|
});
|
|
12937
13193
|
});
|
|
13194
|
+
[autoMonitorLabel, autoMonitorToggle].forEach(control => {
|
|
13195
|
+
['mousedown', 'mouseup', 'click', 'dblclick', 'keydown'].forEach(eventName => {
|
|
13196
|
+
control.addEventListener(eventName, event => event.stopPropagation());
|
|
13197
|
+
});
|
|
13198
|
+
});
|
|
12938
13199
|
|
|
12939
13200
|
searchInput.addEventListener('input', applyRemoteFleetFilters);
|
|
12940
13201
|
filterSelect.addEventListener('change', applyRemoteFleetFilters);
|
|
12941
13202
|
aiToggle.addEventListener('change', applyRemoteFleetFilters);
|
|
13203
|
+
autoMonitorToggle.addEventListener('change', () => {
|
|
13204
|
+
bodyView.dataset.remoteFleetAutoMonitor = autoMonitorToggle.checked ? 'true' : 'false';
|
|
13205
|
+
renderRemoteFleetMonitor(bodyView, nodeModel);
|
|
13206
|
+
});
|
|
12942
13207
|
sortSelect.addEventListener('change', () => {
|
|
12943
13208
|
bodyView.dataset.remoteFleetSort = String(sortSelect.value || 'status');
|
|
12944
13209
|
renderRemoteFleetMonitor(bodyView, nodeModel);
|
|
@@ -13011,9 +13276,67 @@
|
|
|
13011
13276
|
event.preventDefault();
|
|
13012
13277
|
event.stopPropagation();
|
|
13013
13278
|
refreshButton.disabled = true;
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13279
|
+
try {
|
|
13280
|
+
await refreshRemoteFleetNode();
|
|
13281
|
+
} finally {
|
|
13282
|
+
refreshButton.disabled = false;
|
|
13283
|
+
}
|
|
13284
|
+
});
|
|
13285
|
+
|
|
13286
|
+
bodyView.querySelectorAll('[data-remote-fleet-action="live-focus"]').forEach(button => {
|
|
13287
|
+
button.addEventListener('click', event => {
|
|
13288
|
+
event.preventDefault();
|
|
13289
|
+
event.stopPropagation();
|
|
13290
|
+
const deviceId = String(button.dataset.deviceId || '').trim();
|
|
13291
|
+
if (!deviceId) return;
|
|
13292
|
+
bodyView.dataset.remoteFleetFocusDeviceId = deviceId;
|
|
13293
|
+
renderRemoteFleetMonitor(bodyView, nodeModel);
|
|
13294
|
+
});
|
|
13295
|
+
});
|
|
13296
|
+
|
|
13297
|
+
bodyView.querySelectorAll('[data-remote-fleet-action="live-start"]').forEach(button => {
|
|
13298
|
+
button.addEventListener('click', async event => {
|
|
13299
|
+
event.preventDefault();
|
|
13300
|
+
event.stopPropagation();
|
|
13301
|
+
const deviceId = String(button.dataset.deviceId || '').trim();
|
|
13302
|
+
if (!deviceId) return;
|
|
13303
|
+
bodyView.dataset.remoteFleetFocusDeviceId = deviceId;
|
|
13304
|
+
button.disabled = true;
|
|
13305
|
+
setTaskFeedback('Starting focused live stream...');
|
|
13306
|
+
try {
|
|
13307
|
+
const result = await invokeDotNetAsync('StartRemoteFleetLiveStreamFromJs', nodeId, deviceId);
|
|
13308
|
+
await syncRemoteFleetNodeStateFromResult(result);
|
|
13309
|
+
if (result?.success) {
|
|
13310
|
+
setTaskFeedback('Focused live stream started.', 'success');
|
|
13311
|
+
} else {
|
|
13312
|
+
setTaskFeedback(result?.error || 'Live stream start failed.', 'error');
|
|
13313
|
+
}
|
|
13314
|
+
} finally {
|
|
13315
|
+
button.disabled = false;
|
|
13316
|
+
}
|
|
13317
|
+
});
|
|
13318
|
+
});
|
|
13319
|
+
|
|
13320
|
+
bodyView.querySelectorAll('[data-remote-fleet-action="live-stop"]').forEach(button => {
|
|
13321
|
+
button.addEventListener('click', async event => {
|
|
13322
|
+
event.preventDefault();
|
|
13323
|
+
event.stopPropagation();
|
|
13324
|
+
const deviceId = String(button.dataset.deviceId || '').trim();
|
|
13325
|
+
if (!deviceId) return;
|
|
13326
|
+
button.disabled = true;
|
|
13327
|
+
setTaskFeedback('Stopping focused live stream...');
|
|
13328
|
+
try {
|
|
13329
|
+
const result = await invokeDotNetAsync('StopRemoteFleetLiveStreamFromJs', nodeId, deviceId, button.dataset.streamId || '');
|
|
13330
|
+
await syncRemoteFleetNodeStateFromResult(result);
|
|
13331
|
+
if (result?.success) {
|
|
13332
|
+
setTaskFeedback('Focused live stream stopped.', 'success');
|
|
13333
|
+
} else {
|
|
13334
|
+
setTaskFeedback(result?.error || 'Live stream stop failed.', 'error');
|
|
13335
|
+
}
|
|
13336
|
+
} finally {
|
|
13337
|
+
button.disabled = false;
|
|
13338
|
+
}
|
|
13339
|
+
});
|
|
13017
13340
|
});
|
|
13018
13341
|
|
|
13019
13342
|
grid.querySelectorAll('[data-remote-fleet-action="ping-device"]').forEach(button => {
|
|
@@ -13065,6 +13388,34 @@
|
|
|
13065
13388
|
button.disabled = false;
|
|
13066
13389
|
});
|
|
13067
13390
|
});
|
|
13391
|
+
|
|
13392
|
+
if (hasActiveLiveStream) {
|
|
13393
|
+
bodyView._remoteFleetLiveRefreshTimer = setInterval(async () => {
|
|
13394
|
+
if (!document.body.contains(bodyView)) {
|
|
13395
|
+
clearRemoteFleetTimers(bodyView);
|
|
13396
|
+
return;
|
|
13397
|
+
}
|
|
13398
|
+
|
|
13399
|
+
try {
|
|
13400
|
+
await refreshRemoteFleetNode();
|
|
13401
|
+
} catch {
|
|
13402
|
+
clearRemoteFleetTimers(bodyView);
|
|
13403
|
+
}
|
|
13404
|
+
}, REMOTE_FLEET_LIVE_REFRESH_MS);
|
|
13405
|
+
} else if (autoMonitorState && hasMonitorTargets) {
|
|
13406
|
+
bodyView._remoteFleetMonitorRefreshTimer = setInterval(async () => {
|
|
13407
|
+
if (!document.body.contains(bodyView)) {
|
|
13408
|
+
clearRemoteFleetTimers(bodyView);
|
|
13409
|
+
return;
|
|
13410
|
+
}
|
|
13411
|
+
|
|
13412
|
+
try {
|
|
13413
|
+
await refreshRemoteFleetNode();
|
|
13414
|
+
} catch {
|
|
13415
|
+
clearRemoteFleetTimers(bodyView);
|
|
13416
|
+
}
|
|
13417
|
+
}, REMOTE_FLEET_MONITOR_REFRESH_MS);
|
|
13418
|
+
}
|
|
13068
13419
|
}
|
|
13069
13420
|
|
|
13070
13421
|
function bindMemoNodeEvents(container, nodeModel) {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256
|
|
4
|
+
"hash": "sha256-XfKFSqnMBnbJmPnM+j3zriBOOdujMLDI/U8Usvww2jQ=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -123,16 +123,16 @@
|
|
|
123
123
|
"System.m05i39uvk9.dll": "System.dll",
|
|
124
124
|
"netstandard.0xet7jg7ky.dll": "netstandard.dll",
|
|
125
125
|
"System.Private.CoreLib.rkafq04oma.dll": "System.Private.CoreLib.dll",
|
|
126
|
-
"MindExecution.Core.
|
|
127
|
-
"MindExecution.Kernel.
|
|
128
|
-
"MindExecution.Plugins.Admin.
|
|
129
|
-
"MindExecution.Plugins.Business.
|
|
130
|
-
"MindExecution.Plugins.Concept.
|
|
131
|
-
"MindExecution.Plugins.Directory.
|
|
132
|
-
"MindExecution.Plugins.PlanMaster.
|
|
133
|
-
"MindExecution.Plugins.YouTube.
|
|
134
|
-
"MindExecution.Shared.
|
|
135
|
-
"MindExecution.Web.
|
|
126
|
+
"MindExecution.Core.pnw79cgqjx.dll": "MindExecution.Core.dll",
|
|
127
|
+
"MindExecution.Kernel.dt3w864bqn.dll": "MindExecution.Kernel.dll",
|
|
128
|
+
"MindExecution.Plugins.Admin.z93cu32xru.dll": "MindExecution.Plugins.Admin.dll",
|
|
129
|
+
"MindExecution.Plugins.Business.b6da8sg85t.dll": "MindExecution.Plugins.Business.dll",
|
|
130
|
+
"MindExecution.Plugins.Concept.mjooiqft9j.dll": "MindExecution.Plugins.Concept.dll",
|
|
131
|
+
"MindExecution.Plugins.Directory.rjod6rdmly.dll": "MindExecution.Plugins.Directory.dll",
|
|
132
|
+
"MindExecution.Plugins.PlanMaster.1dcrzhsegj.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
133
|
+
"MindExecution.Plugins.YouTube.k75qxhbpp8.dll": "MindExecution.Plugins.YouTube.dll",
|
|
134
|
+
"MindExecution.Shared.y3eqxd3mvo.dll": "MindExecution.Shared.dll",
|
|
135
|
+
"MindExecution.Web.wou9x6mn2f.dll": "MindExecution.Web.dll",
|
|
136
136
|
"dotnet.js": "dotnet.js",
|
|
137
137
|
"dotnet.native.xsn1d6x2kd.js": "dotnet.native.js",
|
|
138
138
|
"dotnet.native.vz0adxojrz.wasm": "dotnet.native.wasm",
|
|
@@ -278,18 +278,18 @@
|
|
|
278
278
|
"System.Xml.XDocument.c539ki6cuq.dll": "sha256-MPTRJkptrL9nGa2tl4kF46+wErNUYRPCGblX3ANoKoY=",
|
|
279
279
|
"System.m05i39uvk9.dll": "sha256-5jDfIdbYAigw7/Q/lMzt5W/+cayGbW9ko9FvuaN1GsQ=",
|
|
280
280
|
"netstandard.0xet7jg7ky.dll": "sha256-xENDv620uJ8fHwLJ2bdhrTHz4QPjvqXOztnk2a4wr0c=",
|
|
281
|
-
"MindExecution.Core.
|
|
282
|
-
"MindExecution.Kernel.
|
|
283
|
-
"MindExecution.Plugins.Concept.
|
|
284
|
-
"MindExecution.Plugins.PlanMaster.
|
|
285
|
-
"MindExecution.Shared.
|
|
286
|
-
"MindExecution.Web.
|
|
281
|
+
"MindExecution.Core.pnw79cgqjx.dll": "sha256-64VJ+VCnq+r7lgfYzm99hPX3yo5u2QCC4guGqsrVTus=",
|
|
282
|
+
"MindExecution.Kernel.dt3w864bqn.dll": "sha256-r0Q9mY7CB+L/3j7KlKlNiyLBlXcwBkPRtjGh0RBZOFs=",
|
|
283
|
+
"MindExecution.Plugins.Concept.mjooiqft9j.dll": "sha256-Qrz35qwSLDAaugzQMJ6YLfWI+jld56cCo+9wOwVobgw=",
|
|
284
|
+
"MindExecution.Plugins.PlanMaster.1dcrzhsegj.dll": "sha256-VZ7SUoDTHQ9MdwII/dBqeaVFpDt6UEFDV5xJHAlskgM=",
|
|
285
|
+
"MindExecution.Shared.y3eqxd3mvo.dll": "sha256-EnE/FEgfwb2Trt9cyLvVEeHE8iSRWYhaftVJUOKLAZI=",
|
|
286
|
+
"MindExecution.Web.wou9x6mn2f.dll": "sha256-YENKxQvH07LxcUCqbFITQtVD2sCcdYNAF9aX0YVtVGs="
|
|
287
287
|
},
|
|
288
288
|
"lazyAssembly": {
|
|
289
|
-
"MindExecution.Plugins.Admin.
|
|
290
|
-
"MindExecution.Plugins.Business.
|
|
291
|
-
"MindExecution.Plugins.Directory.
|
|
292
|
-
"MindExecution.Plugins.YouTube.
|
|
289
|
+
"MindExecution.Plugins.Admin.z93cu32xru.dll": "sha256-aToPZeovhBXkB0URHkzYdYDAmg1+HxsvojgiefL4pkY=",
|
|
290
|
+
"MindExecution.Plugins.Business.b6da8sg85t.dll": "sha256-M1macJ1ZqfBCrj/1WPw2JQxnFtFX31HxydBxQKa3Cgw=",
|
|
291
|
+
"MindExecution.Plugins.Directory.rjod6rdmly.dll": "sha256-hx8N04/7sIYB8PdHSyVTLhPfPb7ZkmqM1RPBB1J0iuw=",
|
|
292
|
+
"MindExecution.Plugins.YouTube.k75qxhbpp8.dll": "sha256-IM43bEjZvj6SqvBrKl8JmAN5NfN6IW8VPi3Z/HarwlQ="
|
|
293
293
|
}
|
|
294
294
|
},
|
|
295
295
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
const base = '_content/MindExecution.Shared/js/';
|
|
561
|
-
const scriptVersion = '20260612-remote-
|
|
561
|
+
const scriptVersion = '20260612-remote-auto-monitor-v468';
|
|
562
562
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
563
563
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
564
564
|
const criticalScripts = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "ok6mf/2a",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "sha256-
|
|
89
|
+
"hash": "sha256-9f7DLlG6ShPyYhu/Db97YKVoFr+RhJC2Ko9E4NsL9Lc=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -410,44 +410,44 @@
|
|
|
410
410
|
"url": "_framework/MimeMapping.og9ys58ylm.dll"
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
|
-
"hash": "sha256-
|
|
414
|
-
"url": "_framework/MindExecution.Core.
|
|
413
|
+
"hash": "sha256-64VJ+VCnq+r7lgfYzm99hPX3yo5u2QCC4guGqsrVTus=",
|
|
414
|
+
"url": "_framework/MindExecution.Core.pnw79cgqjx.dll"
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
|
-
"hash": "sha256-
|
|
418
|
-
"url": "_framework/MindExecution.Kernel.
|
|
417
|
+
"hash": "sha256-r0Q9mY7CB+L/3j7KlKlNiyLBlXcwBkPRtjGh0RBZOFs=",
|
|
418
|
+
"url": "_framework/MindExecution.Kernel.dt3w864bqn.dll"
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
|
-
"hash": "sha256-
|
|
422
|
-
"url": "_framework/MindExecution.Plugins.Admin.
|
|
421
|
+
"hash": "sha256-aToPZeovhBXkB0URHkzYdYDAmg1+HxsvojgiefL4pkY=",
|
|
422
|
+
"url": "_framework/MindExecution.Plugins.Admin.z93cu32xru.dll"
|
|
423
423
|
},
|
|
424
424
|
{
|
|
425
|
-
"hash": "sha256-
|
|
426
|
-
"url": "_framework/MindExecution.Plugins.Business.
|
|
425
|
+
"hash": "sha256-M1macJ1ZqfBCrj/1WPw2JQxnFtFX31HxydBxQKa3Cgw=",
|
|
426
|
+
"url": "_framework/MindExecution.Plugins.Business.b6da8sg85t.dll"
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
"hash": "sha256-
|
|
430
|
-
"url": "_framework/MindExecution.Plugins.Concept.
|
|
429
|
+
"hash": "sha256-Qrz35qwSLDAaugzQMJ6YLfWI+jld56cCo+9wOwVobgw=",
|
|
430
|
+
"url": "_framework/MindExecution.Plugins.Concept.mjooiqft9j.dll"
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
|
-
"hash": "sha256-
|
|
434
|
-
"url": "_framework/MindExecution.Plugins.Directory.
|
|
433
|
+
"hash": "sha256-hx8N04/7sIYB8PdHSyVTLhPfPb7ZkmqM1RPBB1J0iuw=",
|
|
434
|
+
"url": "_framework/MindExecution.Plugins.Directory.rjod6rdmly.dll"
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
"hash": "sha256-
|
|
438
|
-
"url": "_framework/MindExecution.Plugins.PlanMaster.
|
|
437
|
+
"hash": "sha256-VZ7SUoDTHQ9MdwII/dBqeaVFpDt6UEFDV5xJHAlskgM=",
|
|
438
|
+
"url": "_framework/MindExecution.Plugins.PlanMaster.1dcrzhsegj.dll"
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
|
-
"hash": "sha256-
|
|
442
|
-
"url": "_framework/MindExecution.Plugins.YouTube.
|
|
441
|
+
"hash": "sha256-IM43bEjZvj6SqvBrKl8JmAN5NfN6IW8VPi3Z/HarwlQ=",
|
|
442
|
+
"url": "_framework/MindExecution.Plugins.YouTube.k75qxhbpp8.dll"
|
|
443
443
|
},
|
|
444
444
|
{
|
|
445
|
-
"hash": "sha256-
|
|
446
|
-
"url": "_framework/MindExecution.Shared.
|
|
445
|
+
"hash": "sha256-EnE/FEgfwb2Trt9cyLvVEeHE8iSRWYhaftVJUOKLAZI=",
|
|
446
|
+
"url": "_framework/MindExecution.Shared.y3eqxd3mvo.dll"
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
"hash": "sha256-
|
|
450
|
-
"url": "_framework/MindExecution.Web.
|
|
449
|
+
"hash": "sha256-YENKxQvH07LxcUCqbFITQtVD2sCcdYNAF9aX0YVtVGs=",
|
|
450
|
+
"url": "_framework/MindExecution.Web.wou9x6mn2f.dll"
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
453
|
"hash": "sha256-IsZJ91/OW+fHzNqIgEc7Y072ns8z9dGritiSyvR9Wgc=",
|
|
@@ -770,7 +770,7 @@
|
|
|
770
770
|
"url": "_framework/Websocket.Client.vapounvmnl.dll"
|
|
771
771
|
},
|
|
772
772
|
{
|
|
773
|
-
"hash": "sha256-
|
|
773
|
+
"hash": "sha256-10lI3q/nXAGFdelS8ribQw72sOgD3PYExvQX6srRqWA=",
|
|
774
774
|
"url": "_framework/blazor.boot.json"
|
|
775
775
|
},
|
|
776
776
|
{
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
"url": "image-manifest.json"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"hash": "sha256-
|
|
837
|
+
"hash": "sha256-e/vzCKU0rJNUBs7+YbA+jxOZd53T9CbUxhBAJ0yi6oM=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|
|
Binary file
|
|
Binary file
|