@mindexec/cli 0.2.98 → 0.2.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/remote-fleet-render-smoke.mjs +28 -31
- package/server.js +48 -6
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +193 -482
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.y4ipk4t13u.dll → MindExecution.Plugins.Concept.w4znwcrl6x.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.3gd195fq5t.dll → MindExecution.Plugins.PlanMaster.0w4vr40lnz.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.sb0cb9cans.dll → MindExecution.Plugins.YouTube.sdl5n9uv68.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.ib8s249hay.dll → MindExecution.Shared.fprczldv6z.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.bfrevq2q4y.dll → MindExecution.Web.xhlvm1d8ex.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +11 -11
- package/wwwroot/index.html +3 -3
- package/wwwroot/service-worker-assets.js +14 -14
- package/wwwroot/service-worker.js +1 -1
package/package.json
CHANGED
|
@@ -701,7 +701,7 @@ try {
|
|
|
701
701
|
manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
|
|
702
702
|
|
|
703
703
|
let cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
704
|
-
assert.equal(cards.length,
|
|
704
|
+
assert.equal(cards.length, connectedCount);
|
|
705
705
|
assert.equal(bodyView.querySelector('[data-remote-fleet-match-count="true"]'), null);
|
|
706
706
|
assert.equal(bodyView.querySelector('[data-remote-fleet-search="true"]'), null);
|
|
707
707
|
assert.equal(bodyView.querySelectorAll('select').length, 0);
|
|
@@ -723,18 +723,14 @@ try {
|
|
|
723
723
|
assert.equal(statusFooter.querySelectorAll('[data-remote-fleet-status-item]').length, 5);
|
|
724
724
|
assert.ok(statusFooter.querySelector('[data-remote-fleet-status-item="route"]'));
|
|
725
725
|
const initialDetailPanel = bodyView.querySelector('[data-remote-fleet-detail-panel="true"]');
|
|
726
|
-
assert.equal(initialDetailPanel
|
|
726
|
+
assert.equal(initialDetailPanel, null);
|
|
727
727
|
const initialSelectedCard = bodyView.querySelector(`article[data-device-id="${focusedDevice.DeviceId}"]`);
|
|
728
|
-
assert.
|
|
729
|
-
assert.equal(initialSelectedCard?.
|
|
730
|
-
assert.
|
|
731
|
-
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="pin-device"]').length, 1);
|
|
728
|
+
assert.ok(initialSelectedCard);
|
|
729
|
+
assert.equal(initialSelectedCard?.querySelector('[data-remote-fleet-selected-indicator="true"]'), null);
|
|
730
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="pin-device"]').length, 0);
|
|
732
731
|
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="task-device"]').length, 0);
|
|
733
|
-
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="thumbnail-device"]').length,
|
|
734
|
-
assert.
|
|
735
|
-
assert.ok(initialDetailPanel?.textContent.includes('Uptime'));
|
|
736
|
-
assert.ok(initialDetailPanel?.textContent.includes('Mem'));
|
|
737
|
-
assert.ok(initialDetailPanel?.textContent.includes('Load'));
|
|
732
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-action="thumbnail-device"]').length, 0);
|
|
733
|
+
assert.equal(bodyView.querySelectorAll('[data-remote-fleet-frame-badge="true"]').length, 0);
|
|
738
734
|
assert.ok(cards[0]?.querySelector('[data-remote-fleet-device-preview="tile"]'));
|
|
739
735
|
assert.equal(/\b(Seen|Uptime|Mem|Load)\b/.test(cards[0]?.textContent || ''), false);
|
|
740
736
|
assert.match(deviceGrid.style.cssText, /minmax\(132px,\s*1fr\)/);
|
|
@@ -745,7 +741,10 @@ try {
|
|
|
745
741
|
assert.equal(bodyView.dataset.remoteFleetDensity, 'cards');
|
|
746
742
|
assert.match(bodyView.querySelector('[data-remote-fleet-device-grid="true"]')?.style.cssText || '', /minmax\(132px,\s*1fr\)/);
|
|
747
743
|
cards = bodyView.querySelectorAll('article[data-device-id]');
|
|
748
|
-
const patchTarget = devices.find(device =>
|
|
744
|
+
const patchTarget = devices.find(device =>
|
|
745
|
+
device.Connected === true
|
|
746
|
+
&& device.ThumbnailEnabled === true
|
|
747
|
+
&& device.LiveStreamActive !== true);
|
|
749
748
|
assert.ok(patchTarget);
|
|
750
749
|
const patchCard = Array.from(cards).find(card => card.dataset.deviceId === patchTarget.DeviceId);
|
|
751
750
|
const patchPreview = patchCard?.querySelector('[data-remote-fleet-device-preview="tile"]');
|
|
@@ -765,19 +764,21 @@ try {
|
|
|
765
764
|
assert.equal(patchPreview.dataset.remoteFleetPendingFrameUrl || '', '');
|
|
766
765
|
assert.ok(patchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]'));
|
|
767
766
|
assert.equal(patchPreview.querySelector('img[data-remote-fleet-frame-image="true"]')?.dataset.remoteFleetFrameUrl, patchUrl);
|
|
768
|
-
|
|
767
|
+
assert.equal(patchPreview.querySelector('[data-remote-fleet-frame-badge="true"]'), null);
|
|
768
|
+
const alternateDevice = devices.find(device =>
|
|
769
|
+
device.Connected === true
|
|
770
|
+
&& device.DeviceId !== focusedDevice.DeviceId);
|
|
769
771
|
assert.ok(alternateDevice);
|
|
770
772
|
const alternateCard = Array.from(cards).find(card => card.dataset.deviceId === alternateDevice.DeviceId);
|
|
771
773
|
assert.ok(alternateCard);
|
|
772
774
|
alternateCard.dispatchEvent({ type: 'click' });
|
|
773
775
|
assert.equal(bodyView.dataset.remoteFleetSelectedDeviceId, alternateDevice.DeviceId);
|
|
774
|
-
assert.equal(bodyView.querySelector('[data-remote-fleet-detail-panel="true"]')
|
|
776
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-detail-panel="true"]'), null);
|
|
775
777
|
const selectedAfterClick = bodyView.querySelector(`article[data-device-id="${alternateDevice.DeviceId}"]`);
|
|
776
|
-
assert.
|
|
777
|
-
assert.equal(selectedAfterClick?.
|
|
778
|
-
assert.ok(selectedAfterClick?.querySelector('[data-remote-fleet-selected-indicator="true"]'));
|
|
778
|
+
assert.ok(selectedAfterClick);
|
|
779
|
+
assert.equal(selectedAfterClick?.querySelector('[data-remote-fleet-selected-indicator="true"]'), null);
|
|
779
780
|
const livePanel = bodyView.querySelector('[data-remote-fleet-live-panel="true"]');
|
|
780
|
-
assert.equal(livePanel
|
|
781
|
+
assert.equal(livePanel, null);
|
|
781
782
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-visible"]'), null);
|
|
782
783
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="task-connected"]'), null);
|
|
783
784
|
assert.equal(bodyView.querySelector('[data-remote-fleet-task-input="true"]'), null);
|
|
@@ -811,28 +812,24 @@ try {
|
|
|
811
812
|
enabled: false
|
|
812
813
|
});
|
|
813
814
|
|
|
814
|
-
assert.
|
|
815
|
+
assert.equal(bodyView.querySelector('[data-remote-fleet-live-panel="true"]'), null);
|
|
815
816
|
assert.equal(bodyView.querySelector('code'), null);
|
|
816
817
|
assert.equal(bodyView.textContent.includes('npx @mindexec/remote connect'), false);
|
|
817
818
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="copy-command"]'), null);
|
|
818
819
|
assert.equal(bodyView.querySelector('[data-remote-fleet-action="refresh"]'), null);
|
|
819
820
|
assert.equal(bodyView.querySelector('[data-remote-fleet-auto-toggle="true"]'), null);
|
|
820
|
-
assert.
|
|
821
|
-
assert.
|
|
821
|
+
assert.equal(bodyView.textContent.includes('synthetic-render-ai'), false);
|
|
822
|
+
assert.equal(bodyView.textContent.includes('Task timed out waiting for the agent response.'), false);
|
|
822
823
|
const batchSummary = bodyView.querySelector('[data-remote-fleet-task-batch="true"]');
|
|
823
|
-
assert.
|
|
824
|
-
assert.ok(batchSummary.textContent.includes('Render smoke batch'));
|
|
825
|
-
assert.ok(batchSummary.textContent.includes('208/210 done'));
|
|
826
|
-
assert.ok(batchSummary.textContent.includes('1 timed out'));
|
|
824
|
+
assert.equal(batchSummary, null);
|
|
827
825
|
const batchHistory = bodyView.querySelector('[data-remote-fleet-task-history="true"]');
|
|
828
|
-
assert.
|
|
829
|
-
assert.ok(batchHistory.textContent.includes('Previous AI batch'));
|
|
830
|
-
assert.ok(batchHistory.textContent.includes('42/42 done'));
|
|
826
|
+
assert.equal(batchHistory, null);
|
|
831
827
|
const resultPanel = bodyView.querySelector('[data-remote-fleet-task-results="true"]');
|
|
832
|
-
assert.
|
|
833
|
-
assert.ok(resultPanel.textContent.includes('synthetic-render-ai'));
|
|
834
|
-
assert.ok(resultPanel.textContent.includes('Overview AI result visible'));
|
|
828
|
+
assert.equal(resultPanel, null);
|
|
835
829
|
assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
|
|
830
|
+
await wait();
|
|
831
|
+
const liveStartCalls = dotNetCalls.filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs');
|
|
832
|
+
assert.ok(liveStartCalls.length > 1, `expected multiple visible live starts, got ${liveStartCalls.length}`);
|
|
836
833
|
await wait(320);
|
|
837
834
|
assert.ok(dotNetCalls.some(call => call.methodName === 'RefreshRemoteFleetMonitorNodeFromJs'));
|
|
838
835
|
assert.equal(bodyView.dataset.remoteFleetTaskFollowKey, 'render-smoke-batch');
|
package/server.js
CHANGED
|
@@ -2978,6 +2978,12 @@ function isRemoteAgentProcessRunning() {
|
|
|
2978
2978
|
&& !proc.killed;
|
|
2979
2979
|
}
|
|
2980
2980
|
|
|
2981
|
+
function isLocalRemoteHostTargetActive() {
|
|
2982
|
+
const status = remoteHub.getStatus({ includeSecrets: false });
|
|
2983
|
+
return status?.hostTargetActive === true
|
|
2984
|
+
&& (!status.hostTargetHostInstanceId || status.hostTargetHostInstanceId === BRIDGE_INSTANCE_ID);
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2981
2987
|
function resolveRemoteAgentLauncher() {
|
|
2982
2988
|
const localLauncher = path.join(BRIDGE_ROOT, 'node_modules', '@mindexec', 'remote', 'bin', 'mindexec-remote.js');
|
|
2983
2989
|
try {
|
|
@@ -3112,6 +3118,22 @@ async function startRemoteAgentConnection(options = {}) {
|
|
|
3112
3118
|
return { ok: false, error: 'missing-pair-token', agent: serializeRemoteAgentState() };
|
|
3113
3119
|
}
|
|
3114
3120
|
|
|
3121
|
+
if (isLocalRemoteHostTargetActive()) {
|
|
3122
|
+
if (isRemoteAgentProcessRunning()) {
|
|
3123
|
+
await stopRemoteAgentConnection('local-host-target-active');
|
|
3124
|
+
}
|
|
3125
|
+
logEvent(
|
|
3126
|
+
'remote',
|
|
3127
|
+
'managed RemoteAgent connect skipped because this bridge is the active host target',
|
|
3128
|
+
'remote');
|
|
3129
|
+
return {
|
|
3130
|
+
ok: true,
|
|
3131
|
+
skipped: true,
|
|
3132
|
+
reason: 'local-host-target-active',
|
|
3133
|
+
agent: serializeRemoteAgentState()
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3115
3137
|
const activeConnectionKeys = new Set(managers.map(manager => createRemoteAgentConnectionKey(manager, leaseId)));
|
|
3116
3138
|
if (isRemoteAgentProcessRunning()
|
|
3117
3139
|
&& remoteAgentState.ready === true
|
|
@@ -7831,13 +7853,33 @@ app.post('/api/remote/frames', (req, res) => {
|
|
|
7831
7853
|
});
|
|
7832
7854
|
});
|
|
7833
7855
|
|
|
7834
|
-
app.post('/api/remote/host-target', (req, res) => {
|
|
7856
|
+
app.post('/api/remote/host-target', async (req, res) => {
|
|
7835
7857
|
res.setHeader('Cache-Control', 'no-store');
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7858
|
+
try {
|
|
7859
|
+
const result = remoteHub.setHostTarget({
|
|
7860
|
+
enabled: req.body?.enabled !== false,
|
|
7861
|
+
nodeId: req.body?.nodeId,
|
|
7862
|
+
leaseMs: req.body?.leaseMs
|
|
7863
|
+
});
|
|
7864
|
+
if (result?.ok === true && result?.active === true && isLocalRemoteHostTargetActive()) {
|
|
7865
|
+
if (isRemoteAgentProcessRunning()) {
|
|
7866
|
+
await stopRemoteAgentConnection('local-host-target-active');
|
|
7867
|
+
logEvent('remote', 'managed RemoteAgent held stopped while local host target is active', 'remote');
|
|
7868
|
+
}
|
|
7869
|
+
}
|
|
7870
|
+
res.json({
|
|
7871
|
+
...result,
|
|
7872
|
+
agent: serializeRemoteAgentState()
|
|
7873
|
+
});
|
|
7874
|
+
} catch (err) {
|
|
7875
|
+
logError('remote', 'remote host target update failed.', err);
|
|
7876
|
+
res.status(500).json({
|
|
7877
|
+
ok: false,
|
|
7878
|
+
active: false,
|
|
7879
|
+
error: err?.message || String(err),
|
|
7880
|
+
agent: serializeRemoteAgentState()
|
|
7881
|
+
});
|
|
7882
|
+
}
|
|
7841
7883
|
});
|
|
7842
7884
|
|
|
7843
7885
|
app.delete('/api/remote/host-target', (req, res) => {
|
|
@@ -12974,13 +12974,16 @@
|
|
|
12974
12974
|
}
|
|
12975
12975
|
|
|
12976
12976
|
const REMOTE_FLEET_MONITOR_REFRESH_MS = 10000;
|
|
12977
|
+
const REMOTE_FLEET_EMPTY_MONITOR_REFRESH_MS = 2500;
|
|
12977
12978
|
const REMOTE_FLEET_LIVE_REFRESH_MS = 30000;
|
|
12978
|
-
const
|
|
12979
|
-
const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = Math.round(1000 /
|
|
12979
|
+
const REMOTE_FLEET_MONITOR_LIVE_FPS = 10;
|
|
12980
|
+
const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = Math.round(1000 / REMOTE_FLEET_MONITOR_LIVE_FPS);
|
|
12980
12981
|
const REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS = 2000;
|
|
12981
12982
|
const REMOTE_FLEET_FRAME_CANVAS_MAX_DPR = 2;
|
|
12982
12983
|
const REMOTE_FLEET_FRAME_BLOB_CACHE_MS = 10000;
|
|
12983
12984
|
const REMOTE_FLEET_FRAME_BLOB_CACHE_LIMIT = 96;
|
|
12985
|
+
const REMOTE_FLEET_LIVE_FRAME_DECODE_TIMEOUT_MS = 180;
|
|
12986
|
+
const REMOTE_FLEET_THUMBNAIL_FRAME_DECODE_TIMEOUT_MS = 1200;
|
|
12984
12987
|
const REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS = 250;
|
|
12985
12988
|
const REMOTE_FLEET_TASK_FOLLOW_REFRESH_MS = 2000;
|
|
12986
12989
|
const REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS = 60;
|
|
@@ -13299,6 +13302,10 @@
|
|
|
13299
13302
|
return patches;
|
|
13300
13303
|
}
|
|
13301
13304
|
|
|
13305
|
+
function shouldDisplayRemoteFleetMonitorDevice(device) {
|
|
13306
|
+
return isRemoteFleetDeviceConnected(device);
|
|
13307
|
+
}
|
|
13308
|
+
|
|
13302
13309
|
function ensureRemoteFleetFrameImage(preview, frame) {
|
|
13303
13310
|
let image = preview?.querySelector?.('img[data-remote-fleet-frame-image="true"]');
|
|
13304
13311
|
if (image) {
|
|
@@ -13439,6 +13446,42 @@
|
|
|
13439
13446
|
return true;
|
|
13440
13447
|
}
|
|
13441
13448
|
|
|
13449
|
+
function getRemoteFleetFrameDecodeTimeoutMs(frame) {
|
|
13450
|
+
return String(frame?.kind || '').toLowerCase() === 'live'
|
|
13451
|
+
? REMOTE_FLEET_LIVE_FRAME_DECODE_TIMEOUT_MS
|
|
13452
|
+
: REMOTE_FLEET_THUMBNAIL_FRAME_DECODE_TIMEOUT_MS;
|
|
13453
|
+
}
|
|
13454
|
+
|
|
13455
|
+
function withRemoteFleetFrameTimeout(promise, timeoutMs, onTimeout) {
|
|
13456
|
+
const duration = Math.max(50, Number(timeoutMs) || REMOTE_FLEET_LIVE_FRAME_DECODE_TIMEOUT_MS);
|
|
13457
|
+
return new Promise((resolve, reject) => {
|
|
13458
|
+
let settled = false;
|
|
13459
|
+
const timer = setTimeout(() => {
|
|
13460
|
+
if (settled) return;
|
|
13461
|
+
settled = true;
|
|
13462
|
+
try {
|
|
13463
|
+
onTimeout?.();
|
|
13464
|
+
} catch {
|
|
13465
|
+
// best effort only
|
|
13466
|
+
}
|
|
13467
|
+
reject(new Error('remote-frame-decode-timeout'));
|
|
13468
|
+
}, duration);
|
|
13469
|
+
Promise.resolve(promise)
|
|
13470
|
+
.then(value => {
|
|
13471
|
+
if (settled) return;
|
|
13472
|
+
settled = true;
|
|
13473
|
+
clearTimeout(timer);
|
|
13474
|
+
resolve(value);
|
|
13475
|
+
})
|
|
13476
|
+
.catch(error => {
|
|
13477
|
+
if (settled) return;
|
|
13478
|
+
settled = true;
|
|
13479
|
+
clearTimeout(timer);
|
|
13480
|
+
reject(error);
|
|
13481
|
+
});
|
|
13482
|
+
});
|
|
13483
|
+
}
|
|
13484
|
+
|
|
13442
13485
|
async function loadRemoteFleetFrameBitmap(frame) {
|
|
13443
13486
|
if (!frame || !isRemoteFleetFrameSource(frame.frameUrl)) {
|
|
13444
13487
|
return null;
|
|
@@ -13482,8 +13525,12 @@
|
|
|
13482
13525
|
entry.expiresAt = now + REMOTE_FLEET_FRAME_BLOB_CACHE_MS;
|
|
13483
13526
|
}
|
|
13484
13527
|
|
|
13485
|
-
const
|
|
13486
|
-
|
|
13528
|
+
const timeoutMs = getRemoteFleetFrameDecodeTimeoutMs(frame);
|
|
13529
|
+
const blob = await withRemoteFleetFrameTimeout(
|
|
13530
|
+
entry.promise,
|
|
13531
|
+
timeoutMs,
|
|
13532
|
+
() => remoteFleetFrameBlobCache.delete(identity));
|
|
13533
|
+
return await withRemoteFleetFrameTimeout(createImageBitmap(blob), timeoutMs);
|
|
13487
13534
|
}
|
|
13488
13535
|
|
|
13489
13536
|
function getRemoteFleetFrameIdentity(frame) {
|
|
@@ -13602,6 +13649,12 @@
|
|
|
13602
13649
|
placeholder.remove();
|
|
13603
13650
|
}
|
|
13604
13651
|
|
|
13652
|
+
const previewMode = String(preview?.dataset?.remoteFleetDevicePreview || '');
|
|
13653
|
+
if (previewMode === 'tile') {
|
|
13654
|
+
preview.querySelector?.('[data-remote-fleet-frame-badge="true"]')?.remove();
|
|
13655
|
+
return true;
|
|
13656
|
+
}
|
|
13657
|
+
|
|
13605
13658
|
const badge = ensureRemoteFleetFrameBadge(preview, frame);
|
|
13606
13659
|
if (badge) {
|
|
13607
13660
|
const at = frame.receivedAt || frame.capturedAt || '';
|
|
@@ -13718,15 +13771,24 @@
|
|
|
13718
13771
|
return;
|
|
13719
13772
|
}
|
|
13720
13773
|
|
|
13774
|
+
const timeoutMs = getRemoteFleetFrameDecodeTimeoutMs(frame);
|
|
13775
|
+
let settled = false;
|
|
13776
|
+
const complete = (loaded, surface = 'img') => {
|
|
13777
|
+
if (settled) return;
|
|
13778
|
+
settled = true;
|
|
13779
|
+
clearTimeout(timeout);
|
|
13780
|
+
finish(loaded, surface);
|
|
13781
|
+
};
|
|
13782
|
+
const timeout = setTimeout(() => complete(false, 'img-timeout'), timeoutMs);
|
|
13721
13783
|
const loader = new Image();
|
|
13722
13784
|
loader.decoding = 'async';
|
|
13723
13785
|
loader.onload = () => {
|
|
13724
13786
|
const decoded = typeof loader.decode === 'function'
|
|
13725
13787
|
? loader.decode().catch(() => undefined)
|
|
13726
13788
|
: Promise.resolve();
|
|
13727
|
-
decoded.then(() =>
|
|
13789
|
+
decoded.then(() => complete(true, 'img'));
|
|
13728
13790
|
};
|
|
13729
|
-
loader.onerror = () =>
|
|
13791
|
+
loader.onerror = () => complete(false, 'img');
|
|
13730
13792
|
loader.src = frame.frameUrl;
|
|
13731
13793
|
};
|
|
13732
13794
|
|
|
@@ -13782,7 +13844,19 @@
|
|
|
13782
13844
|
}
|
|
13783
13845
|
});
|
|
13784
13846
|
})
|
|
13785
|
-
.catch(
|
|
13847
|
+
.catch(error => {
|
|
13848
|
+
if (frame.kind === 'live') {
|
|
13849
|
+
window.RuntimeTrace?.emit?.('remote.frame.decodeSkipped', {
|
|
13850
|
+
kind: frame.kind,
|
|
13851
|
+
seq: frame.frameSeq,
|
|
13852
|
+
error: error?.message || String(error || '')
|
|
13853
|
+
});
|
|
13854
|
+
finish(false, 'canvas-timeout');
|
|
13855
|
+
return;
|
|
13856
|
+
}
|
|
13857
|
+
|
|
13858
|
+
loadFallbackImage();
|
|
13859
|
+
});
|
|
13786
13860
|
}
|
|
13787
13861
|
|
|
13788
13862
|
function queueRemoteFleetFramePaint(preview, frame) {
|
|
@@ -15068,12 +15142,14 @@
|
|
|
15068
15142
|
const recentTaskBatches = parseRemoteFleetRecentTaskBatches(nodeModel);
|
|
15069
15143
|
const latestTaskBatchKey = getRemoteFleetTaskBatchKey(latestTaskBatch);
|
|
15070
15144
|
const latestTaskBatchActive = isRemoteFleetTaskBatchActive(latestTaskBatch);
|
|
15145
|
+
const showTaskSummarySurfaces = false;
|
|
15071
15146
|
if (latestTaskBatchKey && bodyView.dataset.remoteFleetTaskFollowKey !== latestTaskBatchKey) {
|
|
15072
15147
|
bodyView.dataset.remoteFleetTaskFollowKey = latestTaskBatchKey;
|
|
15073
15148
|
bodyView.dataset.remoteFleetTaskFollowTicks = '0';
|
|
15074
15149
|
}
|
|
15075
15150
|
bodyView.dataset.remoteFleetTaskFollowActive = latestTaskBatchActive ? 'true' : 'false';
|
|
15076
15151
|
const sortedDevices = [...parseRemoteFleetDevices(nodeModel)]
|
|
15152
|
+
.filter(shouldDisplayRemoteFleetMonitorDevice)
|
|
15077
15153
|
.sort((left, right) => compareRemoteFleetDevices(left, right, sortState));
|
|
15078
15154
|
const devices = groupState === 'none'
|
|
15079
15155
|
? sortedDevices
|
|
@@ -15099,11 +15175,8 @@
|
|
|
15099
15175
|
} else {
|
|
15100
15176
|
delete bodyView.dataset.remoteFleetSelectedDeviceId;
|
|
15101
15177
|
}
|
|
15102
|
-
const total =
|
|
15103
|
-
const connected =
|
|
15104
|
-
nodeModel,
|
|
15105
|
-
'RemoteFleetConnectedDeviceCount',
|
|
15106
|
-
devices.filter(isRemoteFleetDeviceConnected).length));
|
|
15178
|
+
const total = devices.length;
|
|
15179
|
+
const connected = devices.filter(isRemoteFleetDeviceConnected).length;
|
|
15107
15180
|
const taskCapableCount = devices.filter(device => isRemoteFleetDeviceConnected(device) && isRemoteFleetDeviceTaskCapable(device)).length;
|
|
15108
15181
|
const aiCapableCount = devices.filter(device => isRemoteFleetDeviceConnected(device) && isRemoteFleetDeviceAiCapable(device)).length;
|
|
15109
15182
|
const hubStatus = getRemoteFleetMetadataValue(nodeModel, 'RemoteFleetHubStatus', 'offline');
|
|
@@ -15376,7 +15449,7 @@
|
|
|
15376
15449
|
`;
|
|
15377
15450
|
bodyView.appendChild(taskFeedback);
|
|
15378
15451
|
|
|
15379
|
-
if (latestTaskBatch) {
|
|
15452
|
+
if (showTaskSummarySurfaces && latestTaskBatch) {
|
|
15380
15453
|
const batchTotal = Number(latestTaskBatch.total ?? latestTaskBatch.Total ?? 0);
|
|
15381
15454
|
const batchQueued = Number(latestTaskBatch.queued ?? latestTaskBatch.Queued ?? 0);
|
|
15382
15455
|
const batchPending = Number(latestTaskBatch.pending ?? latestTaskBatch.Pending ?? 0);
|
|
@@ -15437,7 +15510,7 @@
|
|
|
15437
15510
|
const visibleRecentBatches = recentTaskBatches
|
|
15438
15511
|
.filter(batch => batch && String(batch.batchId ?? batch.BatchId ?? '').trim())
|
|
15439
15512
|
.slice(0, 3);
|
|
15440
|
-
if (visibleRecentBatches.length > 0) {
|
|
15513
|
+
if (showTaskSummarySurfaces && visibleRecentBatches.length > 0) {
|
|
15441
15514
|
const history = document.createElement('div');
|
|
15442
15515
|
history.dataset.remoteFleetTaskHistory = 'true';
|
|
15443
15516
|
history.style.cssText = `
|
|
@@ -15504,7 +15577,7 @@
|
|
|
15504
15577
|
.filter(item => item.status || item.title || item.summary || item.error)
|
|
15505
15578
|
.sort((left, right) => right.updatedMs - left.updatedMs)
|
|
15506
15579
|
.slice(0, 4);
|
|
15507
|
-
if (recentTaskResults.length > 0) {
|
|
15580
|
+
if (showTaskSummarySurfaces && recentTaskResults.length > 0) {
|
|
15508
15581
|
const resultPanel = document.createElement('div');
|
|
15509
15582
|
resultPanel.dataset.remoteFleetTaskResults = 'true';
|
|
15510
15583
|
resultPanel.style.cssText = `
|
|
@@ -15542,150 +15615,6 @@
|
|
|
15542
15615
|
bodyView.appendChild(resultPanel);
|
|
15543
15616
|
}
|
|
15544
15617
|
|
|
15545
|
-
if (focusedDevice) {
|
|
15546
|
-
const focusedId = getRemoteFleetDeviceId(focusedDevice);
|
|
15547
|
-
const focusedName = getRemoteFleetDeviceName(focusedDevice);
|
|
15548
|
-
const liveActive = isRemoteFleetLiveActive(focusedDevice);
|
|
15549
|
-
const liveFrameSource = getRemoteFleetFrameSource(focusedDevice, 'live');
|
|
15550
|
-
const liveFrameAt = String(getRemoteFleetDeviceField(focusedDevice, 'liveFrameReceivedAt', 'LiveFrameReceivedAt', ''));
|
|
15551
|
-
const liveStreamId = String(getRemoteFleetDeviceField(focusedDevice, 'liveStreamId', 'LiveStreamId', ''));
|
|
15552
|
-
const hasLiveFrame = hasRemoteFleetLiveFrame(focusedDevice);
|
|
15553
|
-
const livePanel = document.createElement('section');
|
|
15554
|
-
livePanel.dataset.remoteFleetLivePanel = 'true';
|
|
15555
|
-
livePanel.dataset.deviceId = focusedId;
|
|
15556
|
-
livePanel.style.cssText = `
|
|
15557
|
-
flex: 0 0 auto;
|
|
15558
|
-
display: grid;
|
|
15559
|
-
grid-template-columns: minmax(220px, 0.95fr) minmax(0, 1.25fr);
|
|
15560
|
-
gap: 10px;
|
|
15561
|
-
min-height: 170px;
|
|
15562
|
-
padding: 10px;
|
|
15563
|
-
border-radius: 8px;
|
|
15564
|
-
border: 1px solid rgba(14, 165, 233, 0.24);
|
|
15565
|
-
background: rgba(255, 255, 255, 0.82);
|
|
15566
|
-
`;
|
|
15567
|
-
|
|
15568
|
-
const livePreview = document.createElement('div');
|
|
15569
|
-
livePreview.dataset.remoteFleetDevicePreview = 'focused-live';
|
|
15570
|
-
livePreview.dataset.deviceId = focusedId;
|
|
15571
|
-
livePreview.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : '';
|
|
15572
|
-
livePreview.dataset.remoteFleetFrameSeq = String(getRemoteFleetDeviceField(focusedDevice, 'liveFrameSeq', 'LiveFrameSeq', 0));
|
|
15573
|
-
livePreview.style.cssText = `
|
|
15574
|
-
position: relative;
|
|
15575
|
-
min-width: 0;
|
|
15576
|
-
aspect-ratio: 16 / 9;
|
|
15577
|
-
overflow: hidden;
|
|
15578
|
-
border-radius: 7px;
|
|
15579
|
-
background: linear-gradient(135deg, #111827 0%, #1f2937 100%);
|
|
15580
|
-
border: 1px solid rgba(15, 23, 42, 0.16);
|
|
15581
|
-
`;
|
|
15582
|
-
if (hasLiveFrame) {
|
|
15583
|
-
const image = document.createElement('img');
|
|
15584
|
-
image.dataset.remoteFleetFrameImage = 'true';
|
|
15585
|
-
image.dataset.remoteFleetFrameKind = 'live';
|
|
15586
|
-
image.dataset.remoteFleetFrameSeq = livePreview.dataset.remoteFleetFrameSeq;
|
|
15587
|
-
image.src = liveFrameSource;
|
|
15588
|
-
image.alt = `${focusedName} live screen`;
|
|
15589
|
-
image.decoding = 'async';
|
|
15590
|
-
image.style.cssText = `
|
|
15591
|
-
width: 100%;
|
|
15592
|
-
height: 100%;
|
|
15593
|
-
object-fit: cover;
|
|
15594
|
-
display: block;
|
|
15595
|
-
`;
|
|
15596
|
-
livePreview.appendChild(image);
|
|
15597
|
-
} else {
|
|
15598
|
-
const placeholder = document.createElement('div');
|
|
15599
|
-
placeholder.dataset.remoteFleetScreenPlaceholder = 'true';
|
|
15600
|
-
placeholder.textContent = liveActive ? 'Waiting for live frame' : 'Live view idle';
|
|
15601
|
-
placeholder.style.cssText = `
|
|
15602
|
-
position: absolute;
|
|
15603
|
-
inset: 0;
|
|
15604
|
-
display: flex;
|
|
15605
|
-
align-items: center;
|
|
15606
|
-
justify-content: center;
|
|
15607
|
-
color: rgba(226, 232, 240, 0.82);
|
|
15608
|
-
font-size: 12px;
|
|
15609
|
-
font-weight: 900;
|
|
15610
|
-
letter-spacing: 0;
|
|
15611
|
-
`;
|
|
15612
|
-
livePreview.appendChild(placeholder);
|
|
15613
|
-
}
|
|
15614
|
-
const liveBadge = document.createElement('span');
|
|
15615
|
-
liveBadge.dataset.remoteFleetFrameBadge = 'true';
|
|
15616
|
-
liveBadge.textContent = liveActive
|
|
15617
|
-
? `LIVE ${liveFrameAt ? formatRemoteFleetAge(liveFrameAt) : ''}`.trim()
|
|
15618
|
-
: 'FOCUS';
|
|
15619
|
-
liveBadge.style.cssText = `
|
|
15620
|
-
position: absolute;
|
|
15621
|
-
left: 7px;
|
|
15622
|
-
top: 7px;
|
|
15623
|
-
max-width: calc(100% - 14px);
|
|
15624
|
-
padding: 4px 7px;
|
|
15625
|
-
border-radius: 999px;
|
|
15626
|
-
background: ${liveActive ? 'rgba(220, 38, 38, 0.86)' : 'rgba(15, 23, 42, 0.72)'};
|
|
15627
|
-
color: #ffffff;
|
|
15628
|
-
font-size: 9px;
|
|
15629
|
-
font-weight: 950;
|
|
15630
|
-
line-height: 1;
|
|
15631
|
-
overflow: hidden;
|
|
15632
|
-
text-overflow: ellipsis;
|
|
15633
|
-
white-space: nowrap;
|
|
15634
|
-
letter-spacing: 0;
|
|
15635
|
-
`;
|
|
15636
|
-
livePreview.appendChild(liveBadge);
|
|
15637
|
-
|
|
15638
|
-
const liveInfo = document.createElement('div');
|
|
15639
|
-
liveInfo.style.cssText = `
|
|
15640
|
-
min-width: 0;
|
|
15641
|
-
display: flex;
|
|
15642
|
-
flex-direction: column;
|
|
15643
|
-
justify-content: space-between;
|
|
15644
|
-
gap: 8px;
|
|
15645
|
-
`;
|
|
15646
|
-
const liveTitle = document.createElement('div');
|
|
15647
|
-
liveTitle.style.cssText = 'min-width:0;display:flex;flex-direction:column;gap:3px;';
|
|
15648
|
-
const liveName = document.createElement('strong');
|
|
15649
|
-
liveName.textContent = focusedName;
|
|
15650
|
-
liveName.title = focusedName;
|
|
15651
|
-
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;';
|
|
15652
|
-
const liveMeta = document.createElement('span');
|
|
15653
|
-
liveMeta.textContent = liveActive
|
|
15654
|
-
? `RemoteFast ${getRemoteFleetDeviceField(focusedDevice, 'liveStreamFps', 'LiveStreamFps', 0) || 20} fps`
|
|
15655
|
-
: 'View-only focused screen stream';
|
|
15656
|
-
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;';
|
|
15657
|
-
liveTitle.appendChild(liveName);
|
|
15658
|
-
liveTitle.appendChild(liveMeta);
|
|
15659
|
-
|
|
15660
|
-
const liveActions = document.createElement('div');
|
|
15661
|
-
liveActions.style.cssText = 'display:flex;align-items:center;gap:8px;flex-wrap:wrap;';
|
|
15662
|
-
if (isRemoteFleetDeviceConnected(focusedDevice) && isRemoteFleetLiveCapable(focusedDevice)) {
|
|
15663
|
-
const startLiveButton = createRemoteFleetButton(liveActive ? 'Restart live' : 'Start live', 'Start focused view-only live stream', 'live-start');
|
|
15664
|
-
startLiveButton.dataset.deviceId = focusedId;
|
|
15665
|
-
startLiveButton.style.height = '30px';
|
|
15666
|
-
liveActions.appendChild(startLiveButton);
|
|
15667
|
-
if (liveActive) {
|
|
15668
|
-
const stopLiveButton = createRemoteFleetButton('Stop live', 'Stop focused live stream', 'live-stop');
|
|
15669
|
-
stopLiveButton.dataset.deviceId = focusedId;
|
|
15670
|
-
stopLiveButton.dataset.streamId = liveStreamId;
|
|
15671
|
-
stopLiveButton.style.height = '30px';
|
|
15672
|
-
stopLiveButton.style.borderColor = 'rgba(220, 38, 38, 0.32)';
|
|
15673
|
-
stopLiveButton.style.color = '#b91c1c';
|
|
15674
|
-
liveActions.appendChild(stopLiveButton);
|
|
15675
|
-
}
|
|
15676
|
-
} else {
|
|
15677
|
-
const disabled = document.createElement('span');
|
|
15678
|
-
disabled.textContent = 'Live unavailable';
|
|
15679
|
-
disabled.style.cssText = 'color:#64748b;font-size:11px;font-weight:900;';
|
|
15680
|
-
liveActions.appendChild(disabled);
|
|
15681
|
-
}
|
|
15682
|
-
liveInfo.appendChild(liveTitle);
|
|
15683
|
-
liveInfo.appendChild(liveActions);
|
|
15684
|
-
livePanel.appendChild(livePreview);
|
|
15685
|
-
livePanel.appendChild(liveInfo);
|
|
15686
|
-
bodyView.appendChild(livePanel);
|
|
15687
|
-
}
|
|
15688
|
-
|
|
15689
15618
|
const createDevicePreview = (device, mode = 'tile') => {
|
|
15690
15619
|
const name = getRemoteFleetDeviceName(device);
|
|
15691
15620
|
const connectedDevice = isRemoteFleetDeviceConnected(device);
|
|
@@ -15696,7 +15625,6 @@
|
|
|
15696
15625
|
const previewSource = hasLiveFrame
|
|
15697
15626
|
? getRemoteFleetFrameSource(device, 'live')
|
|
15698
15627
|
: getRemoteFleetFrameSource(device, 'thumbnail');
|
|
15699
|
-
const previewAt = hasLiveFrame ? liveFrameReceivedAt : thumbnailCapturedAt;
|
|
15700
15628
|
const isDetail = mode === 'detail';
|
|
15701
15629
|
|
|
15702
15630
|
const preview = document.createElement('div');
|
|
@@ -15743,231 +15671,9 @@
|
|
|
15743
15671
|
preview.appendChild(placeholder);
|
|
15744
15672
|
}
|
|
15745
15673
|
|
|
15746
|
-
const dot = document.createElement('span');
|
|
15747
|
-
dot.style.cssText = `
|
|
15748
|
-
position: absolute;
|
|
15749
|
-
left: ${isDetail ? '9px' : '6px'};
|
|
15750
|
-
top: ${isDetail ? '9px' : '6px'};
|
|
15751
|
-
width: ${isDetail ? '10px' : '8px'};
|
|
15752
|
-
height: ${isDetail ? '10px' : '8px'};
|
|
15753
|
-
border-radius: 999px;
|
|
15754
|
-
background: ${connectedDevice ? '#10b981' : '#94a3b8'};
|
|
15755
|
-
box-shadow: 0 0 0 3px ${connectedDevice ? 'rgba(16,185,129,0.20)' : 'rgba(148,163,184,0.18)'};
|
|
15756
|
-
`;
|
|
15757
|
-
preview.appendChild(dot);
|
|
15758
|
-
|
|
15759
|
-
if (hasLiveFrame || (isDetail && previewAt)) {
|
|
15760
|
-
const badge = document.createElement('span');
|
|
15761
|
-
badge.dataset.remoteFleetFrameBadge = 'true';
|
|
15762
|
-
badge.textContent = hasLiveFrame
|
|
15763
|
-
? (isDetail && previewAt ? `LIVE ${formatRemoteFleetAge(previewAt)}` : 'LIVE')
|
|
15764
|
-
: formatRemoteFleetAge(previewAt);
|
|
15765
|
-
badge.style.cssText = `
|
|
15766
|
-
position: absolute;
|
|
15767
|
-
right: ${isDetail ? '9px' : '6px'};
|
|
15768
|
-
bottom: ${isDetail ? '9px' : '6px'};
|
|
15769
|
-
max-width: calc(100% - ${isDetail ? '18px' : '12px'});
|
|
15770
|
-
padding: ${isDetail ? '4px 7px' : '3px 6px'};
|
|
15771
|
-
border-radius: 999px;
|
|
15772
|
-
background: ${hasLiveFrame ? 'rgba(220, 38, 38, 0.84)' : 'rgba(15, 23, 42, 0.72)'};
|
|
15773
|
-
color: #e2e8f0;
|
|
15774
|
-
font-size: ${isDetail ? '9px' : '8px'};
|
|
15775
|
-
font-weight: 950;
|
|
15776
|
-
line-height: 1;
|
|
15777
|
-
overflow: hidden;
|
|
15778
|
-
text-overflow: ellipsis;
|
|
15779
|
-
white-space: nowrap;
|
|
15780
|
-
letter-spacing: 0;
|
|
15781
|
-
`;
|
|
15782
|
-
preview.appendChild(badge);
|
|
15783
|
-
}
|
|
15784
|
-
|
|
15785
15674
|
return preview;
|
|
15786
15675
|
};
|
|
15787
15676
|
|
|
15788
|
-
const createSelectedDevicePanel = device => {
|
|
15789
|
-
const panel = document.createElement('aside');
|
|
15790
|
-
panel.dataset.remoteFleetDetailPanel = 'true';
|
|
15791
|
-
panel.style.cssText = `
|
|
15792
|
-
min-width: 0;
|
|
15793
|
-
min-height: 0;
|
|
15794
|
-
overflow-y: auto;
|
|
15795
|
-
display: flex;
|
|
15796
|
-
flex-direction: column;
|
|
15797
|
-
gap: 9px;
|
|
15798
|
-
padding: 10px;
|
|
15799
|
-
border-radius: 8px;
|
|
15800
|
-
border: 1px solid rgba(148, 163, 184, 0.28);
|
|
15801
|
-
background: rgba(255, 255, 255, 0.86);
|
|
15802
|
-
`;
|
|
15803
|
-
|
|
15804
|
-
if (!device) {
|
|
15805
|
-
const empty = document.createElement('div');
|
|
15806
|
-
empty.textContent = 'Select a screen';
|
|
15807
|
-
empty.style.cssText = 'display:flex;align-items:center;justify-content:center;min-height:120px;color:#64748b;font-size:12px;font-weight:900;';
|
|
15808
|
-
panel.appendChild(empty);
|
|
15809
|
-
return panel;
|
|
15810
|
-
}
|
|
15811
|
-
|
|
15812
|
-
const deviceId = getRemoteFleetDeviceId(device);
|
|
15813
|
-
const name = getRemoteFleetDeviceName(device);
|
|
15814
|
-
const connectedDevice = isRemoteFleetDeviceConnected(device);
|
|
15815
|
-
const platform = [device?.platform || device?.Platform, device?.arch || device?.Arch]
|
|
15816
|
-
.filter(Boolean)
|
|
15817
|
-
.join(' / ') || 'unknown';
|
|
15818
|
-
const release = String(device?.release || device?.Release || '');
|
|
15819
|
-
const thumbnailEnabled = device?.thumbnailEnabled === true || device?.ThumbnailEnabled === true;
|
|
15820
|
-
const liveStreamEnabled = isRemoteFleetLiveCapable(device);
|
|
15821
|
-
const liveStreamActive = isRemoteFleetLiveActive(device);
|
|
15822
|
-
const liveStreamId = String(device?.liveStreamId || device?.LiveStreamId || '');
|
|
15823
|
-
const taskEnabled = isRemoteFleetDeviceTaskCapable(device);
|
|
15824
|
-
const aiAssistEnabled = isRemoteFleetDeviceAiCapable(device);
|
|
15825
|
-
const aiModel = String(device?.aiModel || device?.AiModel || '');
|
|
15826
|
-
const latestTaskStatus = String(device?.latestTaskStatus || device?.LatestTaskStatus || '');
|
|
15827
|
-
const latestTaskTitle = String(device?.latestTaskTitle || device?.LatestTaskTitle || '');
|
|
15828
|
-
const latestTaskApproval = String(device?.latestTaskApprovalLevel || device?.LatestTaskApprovalLevel || '');
|
|
15829
|
-
const latestTaskUpdatedAt = String(device?.latestTaskUpdatedAt || device?.LatestTaskUpdatedAt || '');
|
|
15830
|
-
const latestTaskError = String(device?.latestTaskError || device?.LatestTaskError || '');
|
|
15831
|
-
const latestTaskResultModel = String(device?.latestTaskResultModel || device?.LatestTaskResultModel || '');
|
|
15832
|
-
const latestTaskResultResponseId = String(device?.latestTaskResultResponseId || device?.LatestTaskResultResponseId || '');
|
|
15833
|
-
const latestTaskResult = String(device?.latestTaskResultSummary || device?.LatestTaskResultSummary || '');
|
|
15834
|
-
const statusText = connectedDevice
|
|
15835
|
-
? (liveStreamActive ? 'Live' : (aiAssistEnabled ? `AI ${aiModel || 'ready'}` : 'Connected'))
|
|
15836
|
-
: 'Offline';
|
|
15837
|
-
|
|
15838
|
-
panel.dataset.deviceId = deviceId;
|
|
15839
|
-
const detailPreview = createDevicePreview(device, 'detail');
|
|
15840
|
-
detailPreview.style.cursor = 'pointer';
|
|
15841
|
-
detailPreview.addEventListener('dblclick', event => {
|
|
15842
|
-
event.preventDefault();
|
|
15843
|
-
event.stopPropagation();
|
|
15844
|
-
bodyView.dataset.remoteFleetSelectedDeviceId = deviceId;
|
|
15845
|
-
openRemoteFleetControlPopup(bodyView, nodeModel, deviceId);
|
|
15846
|
-
});
|
|
15847
|
-
panel.appendChild(detailPreview);
|
|
15848
|
-
|
|
15849
|
-
const header = document.createElement('div');
|
|
15850
|
-
header.style.cssText = 'display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0;';
|
|
15851
|
-
const titleBox = document.createElement('div');
|
|
15852
|
-
titleBox.style.cssText = 'min-width:0;display:flex;flex-direction:column;gap:3px;';
|
|
15853
|
-
const title = document.createElement('strong');
|
|
15854
|
-
title.textContent = name;
|
|
15855
|
-
title.title = name;
|
|
15856
|
-
title.style.cssText = 'color:#0f172a;font-size:14px;font-weight:950;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
15857
|
-
const subtitle = document.createElement('span');
|
|
15858
|
-
subtitle.textContent = release ? `${platform} ${release}` : platform;
|
|
15859
|
-
subtitle.title = subtitle.textContent;
|
|
15860
|
-
subtitle.style.cssText = 'color:#64748b;font-size:11px;font-weight:750;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
15861
|
-
titleBox.appendChild(title);
|
|
15862
|
-
titleBox.appendChild(subtitle);
|
|
15863
|
-
const status = document.createElement('span');
|
|
15864
|
-
status.textContent = statusText;
|
|
15865
|
-
status.style.cssText = `
|
|
15866
|
-
flex: 0 0 auto;
|
|
15867
|
-
max-width: 82px;
|
|
15868
|
-
padding: 4px 7px;
|
|
15869
|
-
border-radius: 999px;
|
|
15870
|
-
background: ${liveStreamActive ? 'rgba(254, 226, 226, 0.92)' : (connectedDevice ? 'rgba(209, 250, 229, 0.92)' : 'rgba(226, 232, 240, 0.92)')};
|
|
15871
|
-
color: ${liveStreamActive ? '#b91c1c' : (connectedDevice ? '#047857' : '#475569')};
|
|
15872
|
-
font-size: 9px;
|
|
15873
|
-
font-weight: 950;
|
|
15874
|
-
line-height: 1;
|
|
15875
|
-
overflow: hidden;
|
|
15876
|
-
text-overflow: ellipsis;
|
|
15877
|
-
white-space: nowrap;
|
|
15878
|
-
letter-spacing: 0;
|
|
15879
|
-
`;
|
|
15880
|
-
header.appendChild(titleBox);
|
|
15881
|
-
header.appendChild(status);
|
|
15882
|
-
panel.appendChild(header);
|
|
15883
|
-
|
|
15884
|
-
const metrics = document.createElement('div');
|
|
15885
|
-
metrics.style.cssText = 'display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;';
|
|
15886
|
-
const addDetailMetric = (label, value) => {
|
|
15887
|
-
const metric = document.createElement('div');
|
|
15888
|
-
metric.style.cssText = 'min-width:0;padding:7px 8px;border-radius:7px;background:rgba(241,245,249,0.86);border:1px solid rgba(148,163,184,0.16);';
|
|
15889
|
-
const labelEl = document.createElement('div');
|
|
15890
|
-
labelEl.textContent = label;
|
|
15891
|
-
labelEl.style.cssText = 'color:#64748b;font-size:9px;font-weight:850;letter-spacing:0;text-transform:uppercase;';
|
|
15892
|
-
const valueEl = document.createElement('div');
|
|
15893
|
-
valueEl.textContent = value;
|
|
15894
|
-
valueEl.title = value;
|
|
15895
|
-
valueEl.style.cssText = 'color:#0f172a;font-size:12px;font-weight:950;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;';
|
|
15896
|
-
metric.appendChild(labelEl);
|
|
15897
|
-
metric.appendChild(valueEl);
|
|
15898
|
-
metrics.appendChild(metric);
|
|
15899
|
-
};
|
|
15900
|
-
addDetailMetric('Seen', formatRemoteFleetAge(device?.lastSeenAt || device?.LastSeenAt));
|
|
15901
|
-
addDetailMetric('Uptime', formatRemoteFleetDuration(device?.uptimeSec ?? device?.UptimeSec));
|
|
15902
|
-
addDetailMetric('Mem', formatRemoteFleetPercent(device?.usedMemRatio ?? device?.UsedMemRatio));
|
|
15903
|
-
addDetailMetric('Load', formatRemoteFleetNumber(device?.load1 ?? device?.Load1, 2));
|
|
15904
|
-
panel.appendChild(metrics);
|
|
15905
|
-
|
|
15906
|
-
if (latestTaskStatus || latestTaskTitle || latestTaskResult || latestTaskError) {
|
|
15907
|
-
const taskBox = document.createElement('div');
|
|
15908
|
-
const taskTone = latestTaskError || latestTaskStatus === 'failed'
|
|
15909
|
-
? 'error'
|
|
15910
|
-
: (latestTaskStatus === 'completed' ? 'done' : 'pending');
|
|
15911
|
-
taskBox.style.cssText = `
|
|
15912
|
-
display: flex;
|
|
15913
|
-
flex-direction: column;
|
|
15914
|
-
gap: 4px;
|
|
15915
|
-
min-width: 0;
|
|
15916
|
-
padding: 8px 9px;
|
|
15917
|
-
border-radius: 7px;
|
|
15918
|
-
background: ${taskTone === 'error' ? 'rgba(248, 113, 113, 0.12)' : taskTone === 'done' ? 'rgba(16, 185, 129, 0.10)' : 'rgba(37, 99, 235, 0.08)'};
|
|
15919
|
-
border: 1px solid ${taskTone === 'error' ? 'rgba(248, 113, 113, 0.24)' : taskTone === 'done' ? 'rgba(16, 185, 129, 0.20)' : 'rgba(37, 99, 235, 0.16)'};
|
|
15920
|
-
`;
|
|
15921
|
-
const taskLine = document.createElement('div');
|
|
15922
|
-
const taskModeLabel = latestTaskApproval === 'ai-assist' ? 'AI' : 'Task';
|
|
15923
|
-
taskLine.textContent = `${taskModeLabel} ${latestTaskStatus || 'task'}${latestTaskUpdatedAt ? ` - ${formatRemoteFleetAge(latestTaskUpdatedAt)}` : ''}${latestTaskResultModel ? ` - ${latestTaskResultModel}` : ''}`;
|
|
15924
|
-
taskLine.title = latestTaskResultResponseId
|
|
15925
|
-
? `${taskLine.textContent} (${latestTaskResultResponseId})`
|
|
15926
|
-
: taskLine.textContent;
|
|
15927
|
-
taskLine.style.cssText = `color:${taskTone === 'error' ? '#991b1b' : taskTone === 'done' ? '#047857' : '#1d4ed8'};font-size:10px;font-weight:950;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:0;`;
|
|
15928
|
-
const taskSummary = document.createElement('div');
|
|
15929
|
-
taskSummary.textContent = formatRemoteFleetTaskError(latestTaskError) || latestTaskResult || latestTaskTitle || 'Task queued';
|
|
15930
|
-
taskSummary.title = taskSummary.textContent;
|
|
15931
|
-
taskSummary.style.cssText = 'color:#334155;font-size:10px;font-weight:750;line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;letter-spacing:0;';
|
|
15932
|
-
taskBox.appendChild(taskLine);
|
|
15933
|
-
taskBox.appendChild(taskSummary);
|
|
15934
|
-
panel.appendChild(taskBox);
|
|
15935
|
-
}
|
|
15936
|
-
|
|
15937
|
-
const actions = document.createElement('div');
|
|
15938
|
-
actions.style.cssText = 'display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:auto;';
|
|
15939
|
-
if (deviceId) {
|
|
15940
|
-
const pinButton = createRemoteFleetButton('Pin', 'Pin this device as a canvas node', 'pin-device');
|
|
15941
|
-
pinButton.dataset.deviceId = deviceId;
|
|
15942
|
-
actions.appendChild(pinButton);
|
|
15943
|
-
}
|
|
15944
|
-
if (connectedDevice && deviceId) {
|
|
15945
|
-
const focusButton = createRemoteFleetButton('Focus', 'Show this device in focused live panel', 'live-focus');
|
|
15946
|
-
focusButton.dataset.deviceId = deviceId;
|
|
15947
|
-
actions.appendChild(focusButton);
|
|
15948
|
-
if (liveStreamEnabled) {
|
|
15949
|
-
const liveButton = createRemoteFleetButton(liveStreamActive ? 'Stop' : 'Live', liveStreamActive ? 'Stop live stream' : 'Start focused live stream', liveStreamActive ? 'live-stop' : 'live-start');
|
|
15950
|
-
liveButton.dataset.deviceId = deviceId;
|
|
15951
|
-
liveButton.dataset.streamId = liveStreamId;
|
|
15952
|
-
if (liveStreamActive) {
|
|
15953
|
-
liveButton.style.borderColor = 'rgba(220, 38, 38, 0.32)';
|
|
15954
|
-
liveButton.style.color = '#b91c1c';
|
|
15955
|
-
}
|
|
15956
|
-
actions.appendChild(liveButton);
|
|
15957
|
-
}
|
|
15958
|
-
if (thumbnailEnabled) {
|
|
15959
|
-
const thumbnailButton = createRemoteFleetButton('Shot', 'Request thumbnail', 'thumbnail-device');
|
|
15960
|
-
thumbnailButton.dataset.deviceId = deviceId;
|
|
15961
|
-
actions.appendChild(thumbnailButton);
|
|
15962
|
-
}
|
|
15963
|
-
const pingButton = createRemoteFleetButton('Ping', 'Ping device', 'ping-device');
|
|
15964
|
-
pingButton.dataset.deviceId = deviceId;
|
|
15965
|
-
actions.appendChild(pingButton);
|
|
15966
|
-
}
|
|
15967
|
-
panel.appendChild(actions);
|
|
15968
|
-
return panel;
|
|
15969
|
-
};
|
|
15970
|
-
|
|
15971
15677
|
const tileMetrics = getRemoteFleetTileMetrics(densityState);
|
|
15972
15678
|
const tileMinWidth = tileMetrics.tileMinWidth;
|
|
15973
15679
|
const tileMinHeight = tileMetrics.tileMinHeight;
|
|
@@ -15979,9 +15685,8 @@
|
|
|
15979
15685
|
flex: 1 1 auto;
|
|
15980
15686
|
min-height: 0;
|
|
15981
15687
|
overflow: hidden;
|
|
15982
|
-
display:
|
|
15983
|
-
|
|
15984
|
-
gap: 10px;
|
|
15688
|
+
display: flex;
|
|
15689
|
+
flex-direction: column;
|
|
15985
15690
|
align-items: stretch;
|
|
15986
15691
|
box-sizing: border-box;
|
|
15987
15692
|
`;
|
|
@@ -16092,7 +15797,7 @@
|
|
|
16092
15797
|
card.dataset.remoteFleetAction = 'select-device';
|
|
16093
15798
|
card.setAttribute('role', 'button');
|
|
16094
15799
|
card.setAttribute('aria-pressed', isSelected ? 'true' : 'false');
|
|
16095
|
-
card.setAttribute('aria-label', `
|
|
15800
|
+
card.setAttribute('aria-label', `Open remote control for ${name}`);
|
|
16096
15801
|
card.tabIndex = 0;
|
|
16097
15802
|
card.title = name;
|
|
16098
15803
|
card.style.cssText = `
|
|
@@ -16109,37 +15814,13 @@
|
|
|
16109
15814
|
padding: 2px;
|
|
16110
15815
|
border-radius: 8px;
|
|
16111
15816
|
background: #ffffff;
|
|
16112
|
-
border:
|
|
16113
|
-
box-shadow:
|
|
15817
|
+
border: 1px solid ${connectedDevice ? 'rgba(16, 185, 129, 0.28)' : 'rgba(148, 163, 184, 0.22)'};
|
|
15818
|
+
box-shadow: 0 8px 18px rgba(15, 23, 42, 0.05);
|
|
16114
15819
|
cursor: pointer;
|
|
16115
15820
|
pointer-events: auto;
|
|
16116
15821
|
user-select: none;
|
|
16117
15822
|
`;
|
|
16118
15823
|
card.appendChild(createDevicePreview(device, 'tile'));
|
|
16119
|
-
if (isSelected) {
|
|
16120
|
-
const selectedIndicator = document.createElement('span');
|
|
16121
|
-
selectedIndicator.dataset.remoteFleetSelectedIndicator = 'true';
|
|
16122
|
-
selectedIndicator.innerHTML = '<i class="fa-solid fa-check" aria-hidden="true"></i>';
|
|
16123
|
-
selectedIndicator.title = 'Selected screen';
|
|
16124
|
-
selectedIndicator.style.cssText = `
|
|
16125
|
-
position: absolute;
|
|
16126
|
-
right: 6px;
|
|
16127
|
-
top: 6px;
|
|
16128
|
-
width: 18px;
|
|
16129
|
-
height: 18px;
|
|
16130
|
-
display: inline-flex;
|
|
16131
|
-
align-items: center;
|
|
16132
|
-
justify-content: center;
|
|
16133
|
-
border-radius: 999px;
|
|
16134
|
-
background: #2563eb;
|
|
16135
|
-
color: #ffffff;
|
|
16136
|
-
font-size: 9px;
|
|
16137
|
-
line-height: 1;
|
|
16138
|
-
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16), 0 8px 16px rgba(15, 23, 42, 0.16);
|
|
16139
|
-
pointer-events: none;
|
|
16140
|
-
`;
|
|
16141
|
-
card.appendChild(selectedIndicator);
|
|
16142
|
-
}
|
|
16143
15824
|
grid.appendChild(card);
|
|
16144
15825
|
});
|
|
16145
15826
|
|
|
@@ -16168,7 +15849,6 @@
|
|
|
16168
15849
|
monitorWorkspace.appendChild(createRemoteFleetEmptyScreens(nodeModel, densityState));
|
|
16169
15850
|
} else {
|
|
16170
15851
|
monitorWorkspace.appendChild(grid);
|
|
16171
|
-
monitorWorkspace.appendChild(createSelectedDevicePanel(selectedDevice));
|
|
16172
15852
|
}
|
|
16173
15853
|
bodyView.appendChild(monitorWorkspace);
|
|
16174
15854
|
bodyView.appendChild(statusRail);
|
|
@@ -16226,71 +15906,90 @@
|
|
|
16226
15906
|
.filter(card => card.style.display !== 'none')
|
|
16227
15907
|
.map(card => String(card.dataset.deviceId || '').trim())
|
|
16228
15908
|
.filter(Boolean);
|
|
16229
|
-
if (focusedDevice) {
|
|
16230
|
-
const focusedId = getRemoteFleetDeviceId(focusedDevice);
|
|
16231
|
-
if (focusedId) {
|
|
16232
|
-
ids.unshift(focusedId);
|
|
16233
|
-
}
|
|
16234
|
-
}
|
|
16235
15909
|
return Array.from(new Set(ids)).slice(0, 120);
|
|
16236
15910
|
};
|
|
16237
|
-
const
|
|
15911
|
+
const getVisibleLiveDevices = () => {
|
|
15912
|
+
const visibleIds = new Set(getVisibleFrameDeviceIds());
|
|
15913
|
+
return devices
|
|
15914
|
+
.filter(device => {
|
|
15915
|
+
const id = getRemoteFleetDeviceId(device);
|
|
15916
|
+
return id
|
|
15917
|
+
&& visibleIds.has(id)
|
|
15918
|
+
&& isRemoteFleetDeviceConnected(device)
|
|
15919
|
+
&& isRemoteFleetLiveCapable(device);
|
|
15920
|
+
})
|
|
15921
|
+
.slice(0, 120);
|
|
15922
|
+
};
|
|
15923
|
+
const getVisibleLiveFrameDeviceIds = () => {
|
|
16238
15924
|
const ids = [];
|
|
16239
|
-
|
|
16240
|
-
&& isRemoteFleetDeviceConnected(selectedDevice)
|
|
16241
|
-
&& (isRemoteFleetLiveCapable(selectedDevice) || isRemoteFleetLiveActive(selectedDevice))) {
|
|
16242
|
-
pushUniqueFrameDeviceId(ids, selectedDevice);
|
|
16243
|
-
}
|
|
16244
|
-
if (focusedDevice
|
|
16245
|
-
&& isRemoteFleetDeviceConnected(focusedDevice)
|
|
16246
|
-
&& (isRemoteFleetLiveCapable(focusedDevice) || isRemoteFleetLiveActive(focusedDevice))) {
|
|
16247
|
-
pushUniqueFrameDeviceId(ids, focusedDevice);
|
|
16248
|
-
}
|
|
15925
|
+
getVisibleLiveDevices().forEach(device => pushUniqueFrameDeviceId(ids, device));
|
|
16249
15926
|
devices
|
|
16250
15927
|
.filter(device => isRemoteFleetDeviceConnected(device) && isRemoteFleetLiveActive(device))
|
|
16251
|
-
.slice(0, 6)
|
|
16252
15928
|
.forEach(device => pushUniqueFrameDeviceId(ids, device));
|
|
16253
|
-
return ids.slice(0,
|
|
16254
|
-
};
|
|
16255
|
-
const getAutoLiveDevice = () => {
|
|
16256
|
-
if (selectedDevice && isRemoteFleetDeviceConnected(selectedDevice) && isRemoteFleetLiveCapable(selectedDevice)) {
|
|
16257
|
-
return selectedDevice;
|
|
16258
|
-
}
|
|
16259
|
-
if (focusedDevice && isRemoteFleetDeviceConnected(focusedDevice) && isRemoteFleetLiveCapable(focusedDevice)) {
|
|
16260
|
-
return focusedDevice;
|
|
16261
|
-
}
|
|
16262
|
-
return null;
|
|
15929
|
+
return ids.slice(0, 120);
|
|
16263
15930
|
};
|
|
16264
|
-
const
|
|
16265
|
-
|
|
16266
|
-
|
|
15931
|
+
const ensureVisibleRemoteFleetLiveStreams = async () => {
|
|
15932
|
+
if (!(bodyView._remoteFleetAutoLiveStartedIds instanceof Set)) {
|
|
15933
|
+
bodyView._remoteFleetAutoLiveStartedIds = new Set();
|
|
15934
|
+
}
|
|
15935
|
+
const targets = getVisibleLiveDevices()
|
|
15936
|
+
.filter(device => {
|
|
15937
|
+
const deviceId = getRemoteFleetDeviceId(device);
|
|
15938
|
+
return deviceId
|
|
15939
|
+
&& !isRemoteFleetLiveActive(device)
|
|
15940
|
+
&& !bodyView._remoteFleetAutoLiveStartedIds.has(deviceId);
|
|
15941
|
+
});
|
|
15942
|
+
if (targets.length === 0) {
|
|
16267
15943
|
return null;
|
|
16268
15944
|
}
|
|
16269
15945
|
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
return null;
|
|
15946
|
+
if (!(bodyView._remoteFleetAutoLiveStartInFlight instanceof Set)) {
|
|
15947
|
+
bodyView._remoteFleetAutoLiveStartInFlight = new Set();
|
|
16273
15948
|
}
|
|
16274
15949
|
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16278
|
-
|
|
16279
|
-
|
|
16280
|
-
|
|
16281
|
-
success: isRemoteFleetResultSuccess(result),
|
|
16282
|
-
fps: result?.fps || result?.Fps || 0,
|
|
16283
|
-
error: result?.error || result?.Error || ''
|
|
16284
|
-
});
|
|
16285
|
-
if (isRemoteFleetResultSuccess(result)) {
|
|
16286
|
-
await syncRemoteFleetNodeStateFromResult(result);
|
|
15950
|
+
let started = 0;
|
|
15951
|
+
let lastResult = null;
|
|
15952
|
+
for (const target of targets) {
|
|
15953
|
+
const deviceId = getRemoteFleetDeviceId(target);
|
|
15954
|
+
if (!deviceId || bodyView._remoteFleetAutoLiveStartInFlight.has(deviceId)) {
|
|
15955
|
+
continue;
|
|
16287
15956
|
}
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
|
|
16291
|
-
|
|
15957
|
+
|
|
15958
|
+
bodyView._remoteFleetAutoLiveStartInFlight.add(deviceId);
|
|
15959
|
+
try {
|
|
15960
|
+
const result = await invokeDotNetAsync('StartRemoteFleetLiveStreamFromJs', nodeId, deviceId);
|
|
15961
|
+
lastResult = result;
|
|
15962
|
+
const success = isRemoteFleetResultSuccess(result);
|
|
15963
|
+
window.RuntimeTrace?.emit?.('remote.live.autoStart', {
|
|
15964
|
+
nodeId,
|
|
15965
|
+
deviceId,
|
|
15966
|
+
success,
|
|
15967
|
+
fps: result?.fps || result?.Fps || 0,
|
|
15968
|
+
mode: 'visible-grid',
|
|
15969
|
+
error: result?.error || result?.Error || ''
|
|
15970
|
+
});
|
|
15971
|
+
if (success) {
|
|
15972
|
+
started += 1;
|
|
15973
|
+
bodyView._remoteFleetAutoLiveStartedIds.add(deviceId);
|
|
15974
|
+
}
|
|
15975
|
+
} finally {
|
|
15976
|
+
bodyView._remoteFleetAutoLiveStartInFlight.delete(deviceId);
|
|
15977
|
+
}
|
|
15978
|
+
}
|
|
15979
|
+
|
|
15980
|
+
if (started > 0) {
|
|
15981
|
+
try {
|
|
15982
|
+
await refreshRemoteFleetNode();
|
|
15983
|
+
} catch (error) {
|
|
15984
|
+
window.RuntimeTrace?.emit?.('remote.live.autoRefreshFailed', {
|
|
15985
|
+
nodeId,
|
|
15986
|
+
started,
|
|
15987
|
+
error: error?.message || String(error || '')
|
|
15988
|
+
});
|
|
16292
15989
|
}
|
|
16293
15990
|
}
|
|
15991
|
+
|
|
15992
|
+
return lastResult || { success: started > 0, started };
|
|
16294
15993
|
};
|
|
16295
15994
|
const refreshRemoteFleetNode = async () => {
|
|
16296
15995
|
if (bodyView._remoteFleetRefreshInFlight === true) {
|
|
@@ -16311,8 +16010,8 @@
|
|
|
16311
16010
|
applyRemoteFleetFramePatches(bodyView, normalizeRemoteFleetDeviceFramePatches(result));
|
|
16312
16011
|
return result;
|
|
16313
16012
|
};
|
|
16314
|
-
const
|
|
16315
|
-
const deviceIds =
|
|
16013
|
+
const refreshRemoteFleetVisibleLiveFrames = async () => {
|
|
16014
|
+
const deviceIds = getVisibleLiveFrameDeviceIds();
|
|
16316
16015
|
if (deviceIds.length === 0) {
|
|
16317
16016
|
return null;
|
|
16318
16017
|
}
|
|
@@ -16323,6 +16022,27 @@
|
|
|
16323
16022
|
applyRemoteFleetFramePatches(bodyView, patches);
|
|
16324
16023
|
return result;
|
|
16325
16024
|
};
|
|
16025
|
+
const startRemoteFleetMonitorRefreshTimer = (intervalMs, reason = 'monitor') => {
|
|
16026
|
+
const interval = Math.max(1000, Number(intervalMs) || REMOTE_FLEET_MONITOR_REFRESH_MS);
|
|
16027
|
+
bodyView.dataset.remoteFleetRefreshReason = reason;
|
|
16028
|
+
bodyView._remoteFleetMonitorRefreshTimer = setInterval(async () => {
|
|
16029
|
+
if (!document.body.contains(bodyView)) {
|
|
16030
|
+
clearRemoteFleetTimers(bodyView);
|
|
16031
|
+
return;
|
|
16032
|
+
}
|
|
16033
|
+
|
|
16034
|
+
try {
|
|
16035
|
+
await refreshRemoteFleetNode();
|
|
16036
|
+
} catch (error) {
|
|
16037
|
+
window.RuntimeTrace?.emit?.('remote.monitor.refreshFailed', {
|
|
16038
|
+
nodeId,
|
|
16039
|
+
reason,
|
|
16040
|
+
error: error?.message || String(error || '')
|
|
16041
|
+
});
|
|
16042
|
+
clearRemoteFleetTimers(bodyView);
|
|
16043
|
+
}
|
|
16044
|
+
}, interval);
|
|
16045
|
+
};
|
|
16326
16046
|
const prepareRemoteFleetTaskFollow = batch => {
|
|
16327
16047
|
if (!isRemoteFleetTaskBatchActive(batch)) {
|
|
16328
16048
|
bodyView.dataset.remoteFleetTaskFollowActive = 'false';
|
|
@@ -16517,7 +16237,6 @@
|
|
|
16517
16237
|
const deviceId = String(card.dataset.deviceId || '').trim();
|
|
16518
16238
|
if (!deviceId) return;
|
|
16519
16239
|
bodyView.dataset.remoteFleetSelectedDeviceId = deviceId;
|
|
16520
|
-
renderRemoteFleetMonitor(bodyView, nodeModel);
|
|
16521
16240
|
};
|
|
16522
16241
|
card.addEventListener('click', selectCard);
|
|
16523
16242
|
card.addEventListener('keydown', event => {
|
|
@@ -16814,15 +16533,16 @@
|
|
|
16814
16533
|
startRemoteFleetHostLeaseTimer(nodeId, () => setRemoteFleetHostTarget(true, { quiet: true, renew: true }));
|
|
16815
16534
|
}
|
|
16816
16535
|
|
|
16817
|
-
const
|
|
16818
|
-
|
|
16819
|
-
|
|
16536
|
+
const hasVisibleLiveTarget = getVisibleLiveFrameDeviceIds().length > 0
|
|
16537
|
+
|| devices.some(device => isRemoteFleetDeviceConnected(device) && isRemoteFleetLiveCapable(device));
|
|
16538
|
+
if (hasVisibleLiveTarget || hasActiveLiveStream) {
|
|
16539
|
+
ensureVisibleRemoteFleetLiveStreams().catch(error => {
|
|
16820
16540
|
window.RuntimeTrace?.emit?.('remote.live.autoStartFailed', {
|
|
16821
16541
|
nodeId,
|
|
16822
16542
|
error: error?.message || String(error || '')
|
|
16823
16543
|
});
|
|
16824
16544
|
});
|
|
16825
|
-
startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS, () =>
|
|
16545
|
+
startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS, () => refreshRemoteFleetVisibleLiveFrames());
|
|
16826
16546
|
bodyView._remoteFleetLiveRefreshTimer = setInterval(async () => {
|
|
16827
16547
|
if (!document.body.contains(bodyView)) {
|
|
16828
16548
|
clearRemoteFleetTimers(bodyView);
|
|
@@ -16837,18 +16557,9 @@
|
|
|
16837
16557
|
}, REMOTE_FLEET_LIVE_REFRESH_MS);
|
|
16838
16558
|
} else if (autoMonitorState && hasMonitorTargets) {
|
|
16839
16559
|
startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS, () => refreshRemoteFleetVisibleFrames(true));
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
return;
|
|
16844
|
-
}
|
|
16845
|
-
|
|
16846
|
-
try {
|
|
16847
|
-
await refreshRemoteFleetNode();
|
|
16848
|
-
} catch {
|
|
16849
|
-
clearRemoteFleetTimers(bodyView);
|
|
16850
|
-
}
|
|
16851
|
-
}, REMOTE_FLEET_MONITOR_REFRESH_MS);
|
|
16560
|
+
startRemoteFleetMonitorRefreshTimer(REMOTE_FLEET_MONITOR_REFRESH_MS, 'visible-devices');
|
|
16561
|
+
} else if (autoMonitorState) {
|
|
16562
|
+
startRemoteFleetMonitorRefreshTimer(REMOTE_FLEET_EMPTY_MONITOR_REFRESH_MS, 'empty-discovery');
|
|
16852
16563
|
}
|
|
16853
16564
|
}
|
|
16854
16565
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/wwwroot/_framework/{MindExecution.Web.bfrevq2q4y.dll → MindExecution.Web.xhlvm1d8ex.dll}
RENAMED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MindExecution.Web",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-we9qenVtePc2CABTfoN+/D96wdPuqIl4CgKuk3znAUA=",
|
|
5
5
|
"fingerprinting": {
|
|
6
6
|
"Google.Protobuf.9h59ukbel7.dll": "Google.Protobuf.dll",
|
|
7
7
|
"Markdig.d1j7v41cl1.dll": "Markdig.dll",
|
|
@@ -127,12 +127,12 @@
|
|
|
127
127
|
"MindExecution.Kernel.7k773jan4j.dll": "MindExecution.Kernel.dll",
|
|
128
128
|
"MindExecution.Plugins.Admin.nr5ioavpvn.dll": "MindExecution.Plugins.Admin.dll",
|
|
129
129
|
"MindExecution.Plugins.Business.qq63kom73x.dll": "MindExecution.Plugins.Business.dll",
|
|
130
|
-
"MindExecution.Plugins.Concept.
|
|
130
|
+
"MindExecution.Plugins.Concept.w4znwcrl6x.dll": "MindExecution.Plugins.Concept.dll",
|
|
131
131
|
"MindExecution.Plugins.Directory.u6p6pxpwxp.dll": "MindExecution.Plugins.Directory.dll",
|
|
132
|
-
"MindExecution.Plugins.PlanMaster.
|
|
133
|
-
"MindExecution.Plugins.YouTube.
|
|
134
|
-
"MindExecution.Shared.
|
|
135
|
-
"MindExecution.Web.
|
|
132
|
+
"MindExecution.Plugins.PlanMaster.0w4vr40lnz.dll": "MindExecution.Plugins.PlanMaster.dll",
|
|
133
|
+
"MindExecution.Plugins.YouTube.sdl5n9uv68.dll": "MindExecution.Plugins.YouTube.dll",
|
|
134
|
+
"MindExecution.Shared.fprczldv6z.dll": "MindExecution.Shared.dll",
|
|
135
|
+
"MindExecution.Web.xhlvm1d8ex.dll": "MindExecution.Web.dll",
|
|
136
136
|
"dotnet.js": "dotnet.js",
|
|
137
137
|
"dotnet.native.qc8g39g30v.js": "dotnet.native.js",
|
|
138
138
|
"dotnet.native.boem75ye5i.wasm": "dotnet.native.wasm",
|
|
@@ -280,16 +280,16 @@
|
|
|
280
280
|
"netstandard.yvr3prsx0x.dll": "sha256-EksNn8Luo4bOWqJ6X7dIe9qG9oOqwOVzjH2xYyMNi+E=",
|
|
281
281
|
"MindExecution.Core.cdplo34sb2.dll": "sha256-sLc0yEeGYQhFPxxNKLQsHllAhwjKhNn+pfgRY0bHbpo=",
|
|
282
282
|
"MindExecution.Kernel.7k773jan4j.dll": "sha256-B5H6hzB6g8sWLqXUoXifv8CbLqVt7g1lLkkinTBKF8E=",
|
|
283
|
-
"MindExecution.Plugins.Concept.
|
|
284
|
-
"MindExecution.Plugins.PlanMaster.
|
|
285
|
-
"MindExecution.Shared.
|
|
286
|
-
"MindExecution.Web.
|
|
283
|
+
"MindExecution.Plugins.Concept.w4znwcrl6x.dll": "sha256-oNGAmbTjkFdVfZeYbc4jYWtyQa3c8Tle5LIXoFye4yo=",
|
|
284
|
+
"MindExecution.Plugins.PlanMaster.0w4vr40lnz.dll": "sha256-gPWCEzDE7cJLOFTJOhja3JXJzkHFWd4dzfRdsdTxwps=",
|
|
285
|
+
"MindExecution.Shared.fprczldv6z.dll": "sha256-veGmVlpQw2b1zDaUWReHRSLbiZ2IloG79uo1GLlduEo=",
|
|
286
|
+
"MindExecution.Web.xhlvm1d8ex.dll": "sha256-azcD8wLJIxuNSplzTVvh2ndLwdcu20xz1t8Jh23Dr7Q="
|
|
287
287
|
},
|
|
288
288
|
"lazyAssembly": {
|
|
289
289
|
"MindExecution.Plugins.Admin.nr5ioavpvn.dll": "sha256-TWIfHGuEUUD1JtyuhfH4NM5JkvqAt8KcDVrWxvmwnVc=",
|
|
290
290
|
"MindExecution.Plugins.Business.qq63kom73x.dll": "sha256-4lgIcKclWQIjijrBJJFu84fgAH4MsDCN/myhG/K9OOU=",
|
|
291
291
|
"MindExecution.Plugins.Directory.u6p6pxpwxp.dll": "sha256-BjJ6/XNfp5wd/1RTdh99X9RR0I1GV6t4bp5A+RlAK9s=",
|
|
292
|
-
"MindExecution.Plugins.YouTube.
|
|
292
|
+
"MindExecution.Plugins.YouTube.sdl5n9uv68.dll": "sha256-gNZE7M6cqiF9aEJYdZtUzt5bYPkh5Be7LKuyh286u2Q="
|
|
293
293
|
}
|
|
294
294
|
},
|
|
295
295
|
"cacheBootResources": true,
|
package/wwwroot/index.html
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<title>MindExec | Run your ideas as AI task graphs</title>
|
|
8
8
|
<meta name="description" content="MindExec is an AI execution canvas for solo builders, researchers, developers, and creators. Start with free browser tools, then move serious work into saved MindCanvas projects." />
|
|
9
9
|
<base href="/" />
|
|
10
|
-
<link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260616-mdm-
|
|
11
|
-
<link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260616-mdm-
|
|
10
|
+
<link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260616-mdm-screen-wall-v560" />
|
|
11
|
+
<link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260616-mdm-screen-wall-v560" />
|
|
12
12
|
<!-- ?쇄뼹??Font Awesome (local) ?쇄뼹??-->
|
|
13
13
|
<link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
|
|
14
14
|
<!-- ?꿎뼯??-->
|
|
@@ -579,7 +579,7 @@
|
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
const base = '_content/MindExecution.Shared/js/';
|
|
582
|
-
const scriptVersion = '20260616-mdm-
|
|
582
|
+
const scriptVersion = '20260616-mdm-screen-wall-v560';
|
|
583
583
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
584
584
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
585
585
|
const criticalScripts = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "i4nijHuW",
|
|
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-MWVSM/VwUCyDL+ohY/7e6qDkkosGiE9E3t3DbiGJJEs=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -426,28 +426,28 @@
|
|
|
426
426
|
"url": "_framework/MindExecution.Plugins.Business.qq63kom73x.dll"
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
"hash": "sha256-
|
|
430
|
-
"url": "_framework/MindExecution.Plugins.Concept.
|
|
429
|
+
"hash": "sha256-oNGAmbTjkFdVfZeYbc4jYWtyQa3c8Tle5LIXoFye4yo=",
|
|
430
|
+
"url": "_framework/MindExecution.Plugins.Concept.w4znwcrl6x.dll"
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
433
|
"hash": "sha256-BjJ6/XNfp5wd/1RTdh99X9RR0I1GV6t4bp5A+RlAK9s=",
|
|
434
434
|
"url": "_framework/MindExecution.Plugins.Directory.u6p6pxpwxp.dll"
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
"hash": "sha256-
|
|
438
|
-
"url": "_framework/MindExecution.Plugins.PlanMaster.
|
|
437
|
+
"hash": "sha256-gPWCEzDE7cJLOFTJOhja3JXJzkHFWd4dzfRdsdTxwps=",
|
|
438
|
+
"url": "_framework/MindExecution.Plugins.PlanMaster.0w4vr40lnz.dll"
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
|
-
"hash": "sha256-
|
|
442
|
-
"url": "_framework/MindExecution.Plugins.YouTube.
|
|
441
|
+
"hash": "sha256-gNZE7M6cqiF9aEJYdZtUzt5bYPkh5Be7LKuyh286u2Q=",
|
|
442
|
+
"url": "_framework/MindExecution.Plugins.YouTube.sdl5n9uv68.dll"
|
|
443
443
|
},
|
|
444
444
|
{
|
|
445
|
-
"hash": "sha256-
|
|
446
|
-
"url": "_framework/MindExecution.Shared.
|
|
445
|
+
"hash": "sha256-veGmVlpQw2b1zDaUWReHRSLbiZ2IloG79uo1GLlduEo=",
|
|
446
|
+
"url": "_framework/MindExecution.Shared.fprczldv6z.dll"
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
"hash": "sha256-
|
|
450
|
-
"url": "_framework/MindExecution.Web.
|
|
449
|
+
"hash": "sha256-azcD8wLJIxuNSplzTVvh2ndLwdcu20xz1t8Jh23Dr7Q=",
|
|
450
|
+
"url": "_framework/MindExecution.Web.xhlvm1d8ex.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-vjnwzCMMAs+8it6vEUPeOD7pI/ekFwMr484KaDdpugE=",
|
|
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-sZOOfmQyxo9FNFTY9d3r4uYgRhh9Z2b5ve3569JDamU=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|