@mindexec/cli 0.2.51 → 0.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. package/package.json +1 -1
  2. package/remote-hub.js +35 -0
  3. package/scripts/remote-http-smoke.mjs +34 -0
  4. package/server.js +22 -3
  5. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +302 -4
  6. package/wwwroot/_framework/MindExecution.Core.fu1rl67yt3.dll +0 -0
  7. package/wwwroot/_framework/{MindExecution.Kernel.necgouk2lu.dll → MindExecution.Kernel.cqcbagjpqb.dll} +0 -0
  8. package/wwwroot/_framework/{MindExecution.Plugins.Admin.i1bsxgnkwb.dll → MindExecution.Plugins.Admin.tsn0j478un.dll} +0 -0
  9. package/wwwroot/_framework/{MindExecution.Plugins.Business.opnf5esnox.dll → MindExecution.Plugins.Business.xg74dmn0vz.dll} +0 -0
  10. package/wwwroot/_framework/{MindExecution.Plugins.Concept.3c5vvjh1ax.dll → MindExecution.Plugins.Concept.j0zntvuecv.dll} +0 -0
  11. package/wwwroot/_framework/{MindExecution.Plugins.Directory.mcs5ilkrby.dll → MindExecution.Plugins.Directory.9i4bd043ia.dll} +0 -0
  12. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.ofkqkx5csm.dll → MindExecution.Plugins.PlanMaster.vml3qie2ji.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.si9ylbnkqo.dll → MindExecution.Plugins.YouTube.0gfbwq1jfg.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Shared.w5v05uuccd.dll → MindExecution.Shared.f3bclzo6k4.dll} +0 -0
  15. package/wwwroot/_framework/MindExecution.Web.4jhsxoiqgz.dll +0 -0
  16. package/wwwroot/_framework/blazor.boot.json +21 -21
  17. package/wwwroot/index.html +3 -3
  18. package/wwwroot/service-worker-assets.js +24 -24
  19. package/wwwroot/service-worker.js +1 -1
  20. package/wwwroot/_framework/MindExecution.Core.fv9epd367q.dll +0 -0
  21. package/wwwroot/_framework/MindExecution.Web.y71txqhdir.dll +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindexec/cli",
3
- "version": "0.2.51",
3
+ "version": "0.2.53",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
package/remote-hub.js CHANGED
@@ -304,6 +304,7 @@ export function createRemoteHub(options = {}) {
304
304
  DEFAULT_AGENT_TASK_TIMEOUT_MS);
305
305
  const managerPackage = safeString(options.managerPackage ?? env.MINDEXEC_MANAGER_PACKAGE ?? '@mindexec/cli', 128);
306
306
  const managerVersion = safeString(options.managerVersion ?? env.MINDEXEC_MANAGER_VERSION ?? '', 64);
307
+ const hostInstanceId = safeString(options.hostInstanceId ?? env.MINDEXEC_BRIDGE_INSTANCE_ID ?? crypto.randomUUID(), 128) || crypto.randomUUID();
307
308
  const publicEndpoint = safeString(env.MINDEXEC_REMOTE_PUBLIC_ENDPOINT || env.REMOTE_HUB_PUBLIC_ENDPOINT, 256);
308
309
  const publicHost = safeString(env.MINDEXEC_REMOTE_PUBLIC_HOST || env.REMOTE_HUB_PUBLIC_HOST, 128);
309
310
  const pairToken = safeString(
@@ -367,6 +368,7 @@ export function createRemoteHub(options = {}) {
367
368
  active: false,
368
369
  nodeId: '',
369
370
  leaseId: '',
371
+ hostInstanceId: '',
370
372
  endpoint: '',
371
373
  activatedAt: '',
372
374
  updatedAt: '',
@@ -378,6 +380,7 @@ export function createRemoteHub(options = {}) {
378
380
  active: true,
379
381
  nodeId: target.nodeId,
380
382
  leaseId: target.leaseId,
383
+ hostInstanceId: target.hostInstanceId || hostInstanceId,
381
384
  endpoint: target.endpoint,
382
385
  activatedAt: target.activatedAt,
383
386
  updatedAt: target.updatedAt,
@@ -437,6 +440,7 @@ export function createRemoteHub(options = {}) {
437
440
  hostTarget = {
438
441
  nodeId,
439
442
  leaseId: activeSameNode && previous?.leaseId ? previous.leaseId : crypto.randomUUID(),
443
+ hostInstanceId,
440
444
  endpoint: getAgentEndpoint(),
441
445
  activatedAt: activeSameNode && previous?.activatedAt ? previous.activatedAt : now.toISOString(),
442
446
  updatedAt: now.toISOString(),
@@ -469,6 +473,7 @@ export function createRemoteHub(options = {}) {
469
473
  taskTimeoutMs,
470
474
  managerPackage,
471
475
  managerVersion,
476
+ hostInstanceId,
472
477
  agentPackage: '@mindexec/remote',
473
478
  agentEndpoint: getAgentEndpoint(),
474
479
  pairToken: includeSecrets ? pairToken : undefined,
@@ -480,6 +485,7 @@ export function createRemoteHub(options = {}) {
480
485
  hostTargetActive: activeHostTarget.active,
481
486
  hostTargetNodeId: activeHostTarget.nodeId,
482
487
  hostTargetLeaseId: activeHostTarget.leaseId,
488
+ hostTargetHostInstanceId: activeHostTarget.hostInstanceId,
483
489
  hostTargetEndpoint: activeHostTarget.endpoint,
484
490
  hostTargetActivatedAt: activeHostTarget.activatedAt,
485
491
  hostTargetUpdatedAt: activeHostTarget.updatedAt,
@@ -506,6 +512,34 @@ export function createRemoteHub(options = {}) {
506
512
  });
507
513
  }
508
514
 
515
+ function listDeviceFrames(options = {}) {
516
+ const ids = Array.isArray(options.deviceIds)
517
+ ? options.deviceIds.map(value => safeString(value, 160)).filter(Boolean)
518
+ : [];
519
+ const idSet = ids.length > 0 ? new Set(ids) : null;
520
+ const includeThumbnail = options.includeThumbnail !== false;
521
+ const includeLive = options.includeLive !== false;
522
+
523
+ return [...devices.values()]
524
+ .filter(device => !idSet || idSet.has(device.deviceId))
525
+ .map(device => ({
526
+ deviceId: device.deviceId,
527
+ connected: device.connected === true,
528
+ thumbnailEnabled: readCapabilityFlag(device.capabilities, 'thumbnail'),
529
+ liveStreamActive: device.activeLiveStream?.active === true,
530
+ liveStreamId: device.activeLiveStream?.streamId || '',
531
+ liveStreamFps: Number(device.activeLiveStream?.fps || 0),
532
+ liveStreamLastFrameAt: device.activeLiveStream?.lastFrameAt || '',
533
+ thumbnail: includeThumbnail
534
+ ? serializeRemoteFrame(device.latestThumbnail, device.deviceId, 'thumbnail', { includeDataUrl: false })
535
+ : null,
536
+ live: includeLive
537
+ ? serializeRemoteFrame(device.latestLiveFrame, device.deviceId, 'live', { includeDataUrl: false })
538
+ : null
539
+ }))
540
+ .sort((a, b) => String(a.deviceId).localeCompare(String(b.deviceId)));
541
+ }
542
+
509
543
  function listTaskBatches() {
510
544
  return [...taskBatches.values()]
511
545
  .map(serializeTaskBatch)
@@ -2094,6 +2128,7 @@ export function createRemoteHub(options = {}) {
2094
2128
  listDevices,
2095
2129
  listTaskBatches,
2096
2130
  getLatestTaskBatch,
2131
+ listDeviceFrames,
2097
2132
  disconnectDevice,
2098
2133
  sendCommand,
2099
2134
  requestAgentTask,
@@ -377,6 +377,23 @@ async function runSyntheticEnabledSmoke() {
377
377
  assert.ok(urlOnlyThumbnailDevice?.latestThumbnail?.framePath);
378
378
  assert.ok(!('dataUrl' in urlOnlyThumbnailDevice.latestThumbnail));
379
379
 
380
+ const thumbnailFramesOnly = await fetchJson(`${baseUrl}/api/remote/frames`, {
381
+ method: 'POST',
382
+ token: BRIDGE_TOKEN,
383
+ body: JSON.stringify({
384
+ deviceIds: [thumbnailTarget.deviceId],
385
+ includeThumbnail: true,
386
+ includeLive: true
387
+ })
388
+ });
389
+ assert.equal(thumbnailFramesOnly.ok, true, JSON.stringify(thumbnailFramesOnly.payload));
390
+ assert.equal(thumbnailFramesOnly.payload?.ok, true);
391
+ assert.equal(thumbnailFramesOnly.payload?.frames?.length, 1);
392
+ assert.equal(thumbnailFramesOnly.payload.frames[0].deviceId, thumbnailTarget.deviceId);
393
+ assert.equal(thumbnailFramesOnly.payload.frames[0].thumbnailEnabled, true);
394
+ assert.ok(String(thumbnailFramesOnly.payload.frames[0].thumbnail?.framePath || '').includes(`/api/remote/devices/${encodeURIComponent(thumbnailTarget.deviceId)}/thumbnail?`));
395
+ assert.ok(!('dataUrl' in thumbnailFramesOnly.payload.frames[0].thumbnail));
396
+
380
397
  const liveTarget = devicesResult.payload.devices.find(device =>
381
398
  device.connected && device.capabilities?.liveStream);
382
399
  assert.ok(liveTarget);
@@ -419,6 +436,23 @@ async function runSyntheticEnabledSmoke() {
419
436
  const badLiveSeq = await fetchBinary(`${baseUrl}${liveFrame.payload.frame.framePath.replace(/seq=\d+/, 'seq=999999')}`);
420
437
  assert.equal(badLiveSeq.status, 401);
421
438
 
439
+ const liveFramesOnly = await fetchJson(`${baseUrl}/api/remote/frames`, {
440
+ method: 'POST',
441
+ token: BRIDGE_TOKEN,
442
+ body: JSON.stringify({
443
+ deviceIds: [liveTarget.deviceId],
444
+ includeThumbnail: true,
445
+ includeLive: true
446
+ })
447
+ });
448
+ assert.equal(liveFramesOnly.ok, true, JSON.stringify(liveFramesOnly.payload));
449
+ assert.equal(liveFramesOnly.payload?.ok, true);
450
+ assert.equal(liveFramesOnly.payload?.frames?.length, 1);
451
+ assert.equal(liveFramesOnly.payload.frames[0].deviceId, liveTarget.deviceId);
452
+ assert.equal(liveFramesOnly.payload.frames[0].liveStreamActive, true);
453
+ assert.ok(String(liveFramesOnly.payload.frames[0].live?.framePath || '').includes(`/api/remote/devices/${encodeURIComponent(liveTarget.deviceId)}/live/frame?`));
454
+ assert.ok(!('dataUrl' in liveFramesOnly.payload.frames[0].live));
455
+
422
456
  const liveStop = await fetchJson(`${baseUrl}/api/remote/devices/${encodeURIComponent(liveTarget.deviceId)}/live/stop`, {
423
457
  method: 'POST',
424
458
  token: BRIDGE_TOKEN,
package/server.js CHANGED
@@ -33,8 +33,9 @@ const app = express();
33
33
  const PORT = normalizePort(process.env.BRIDGE_PORT);
34
34
  const BRIDGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
35
35
  const PACKAGE_INFO = JSON.parse(readFileSync(path.join(BRIDGE_ROOT, 'package.json'), 'utf8'));
36
- const BRIDGE_PACKAGE_NAME = String(PACKAGE_INFO.name || '@mindexec/cli');
37
- const BRIDGE_VERSION = String(PACKAGE_INFO.version || '0.1.0');
36
+ const BRIDGE_PACKAGE_NAME = String(PACKAGE_INFO.name || '@mindexec/cli');
37
+ const BRIDGE_VERSION = String(PACKAGE_INFO.version || '0.1.0');
38
+ const BRIDGE_INSTANCE_ID = String(process.env.MINDEXEC_BRIDGE_INSTANCE_ID || crypto.randomUUID()).trim() || crypto.randomUUID();
38
39
  const TREE_SITTER_GRAMMAR_DIR = path.join(BRIDGE_ROOT, 'tree-sitter-grammars');
39
40
  const VERBOSE_CODEX_TRACE = /^(1|true|yes|on)$/i.test(String(process.env.BRIDGE_VERBOSE_CODEX || ''));
40
41
  const COLOR_LOGS_ENABLED = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;
@@ -2515,7 +2516,8 @@ const remoteHub = createRemoteHub({
2515
2516
  logError,
2516
2517
  emitEvent: emitBridgeEvent,
2517
2518
  managerPackage: BRIDGE_PACKAGE_NAME,
2518
- managerVersion: BRIDGE_VERSION
2519
+ managerVersion: BRIDGE_VERSION,
2520
+ hostInstanceId: BRIDGE_INSTANCE_ID
2519
2521
  });
2520
2522
 
2521
2523
  const REMOTE_AGENT_STDIO_TAIL_CHARS = 12000;
@@ -7282,6 +7284,23 @@ app.get('/api/remote/devices', (req, res) => {
7282
7284
  });
7283
7285
  });
7284
7286
 
7287
+ app.post('/api/remote/frames', (req, res) => {
7288
+ res.setHeader('Cache-Control', 'no-store');
7289
+ const deviceIds = Array.isArray(req.body?.deviceIds)
7290
+ ? req.body.deviceIds.map(value => String(value || '').trim()).filter(Boolean).slice(0, 120)
7291
+ : [];
7292
+ const frames = remoteHub.listDeviceFrames({
7293
+ deviceIds,
7294
+ includeThumbnail: req.body?.includeThumbnail !== false,
7295
+ includeLive: req.body?.includeLive !== false
7296
+ });
7297
+ res.json({
7298
+ ok: true,
7299
+ total: frames.length,
7300
+ frames
7301
+ });
7302
+ });
7303
+
7285
7304
  app.post('/api/remote/host-target', (req, res) => {
7286
7305
  res.setHeader('Cache-Control', 'no-store');
7287
7306
  res.json(remoteHub.setHostTarget({
@@ -12765,8 +12765,10 @@
12765
12765
  return select;
12766
12766
  }
12767
12767
 
12768
- const REMOTE_FLEET_MONITOR_REFRESH_MS = 5000;
12769
- const REMOTE_FLEET_LIVE_REFRESH_MS = 1000;
12768
+ const REMOTE_FLEET_MONITOR_REFRESH_MS = 10000;
12769
+ const REMOTE_FLEET_LIVE_REFRESH_MS = 5000;
12770
+ const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = 50;
12771
+ const REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS = 2000;
12770
12772
  const REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS = 250;
12771
12773
  const REMOTE_FLEET_TASK_FOLLOW_REFRESH_MS = 2000;
12772
12774
  const REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS = 60;
@@ -12917,6 +12919,12 @@
12917
12919
  clearInterval(bodyView._remoteFleetMonitorRefreshTimer);
12918
12920
  bodyView._remoteFleetMonitorRefreshTimer = null;
12919
12921
  }
12922
+ if (bodyView._remoteFleetFrameLoopRaf) {
12923
+ cancelRemoteFleetFrameLoopFrame(bodyView._remoteFleetFrameLoopRaf);
12924
+ bodyView._remoteFleetFrameLoopRaf = null;
12925
+ }
12926
+ bodyView._remoteFleetFrameLoopActive = false;
12927
+ bodyView._remoteFleetFrameRefreshInFlight = false;
12920
12928
  if (bodyView._remoteFleetTaskFollowTimer) {
12921
12929
  clearTimeout(bodyView._remoteFleetTaskFollowTimer);
12922
12930
  bodyView._remoteFleetTaskFollowTimer = null;
@@ -12927,6 +12935,38 @@
12927
12935
  }
12928
12936
  }
12929
12937
 
12938
+ function requestRemoteFleetFrameLoopFrame(callback) {
12939
+ if (typeof requestAnimationFrame === 'function') {
12940
+ return {
12941
+ kind: 'raf',
12942
+ id: requestAnimationFrame(callback)
12943
+ };
12944
+ }
12945
+
12946
+ return {
12947
+ kind: 'timeout',
12948
+ id: setTimeout(
12949
+ () => callback(typeof performance !== 'undefined' ? performance.now() : Date.now()),
12950
+ 33
12951
+ )
12952
+ };
12953
+ }
12954
+
12955
+ function cancelRemoteFleetFrameLoopFrame(handle) {
12956
+ if (!handle) {
12957
+ return;
12958
+ }
12959
+
12960
+ if (handle.kind === 'timeout') {
12961
+ clearTimeout(handle.id);
12962
+ return;
12963
+ }
12964
+
12965
+ if (typeof cancelAnimationFrame === 'function') {
12966
+ cancelAnimationFrame(handle.id);
12967
+ }
12968
+ }
12969
+
12930
12970
  function getRemoteFleetDeviceField(device, camelKey, pascalKey, fallback = '') {
12931
12971
  const value = device?.[camelKey] ?? device?.[pascalKey] ?? fallback;
12932
12972
  return value === undefined || value === null ? fallback : value;
@@ -12983,6 +13023,200 @@
12983
13023
  || getRemoteFleetDeviceField(device, 'thumbnailDataUrl', 'ThumbnailDataUrl', ''));
12984
13024
  }
12985
13025
 
13026
+ function getRemoteFleetFrameSeq(device, frameKind) {
13027
+ const raw = frameKind === 'live'
13028
+ ? getRemoteFleetDeviceField(device, 'liveFrameSeq', 'LiveFrameSeq', 0)
13029
+ : getRemoteFleetDeviceField(device, 'thumbnailFrameSeq', 'ThumbnailFrameSeq', 0);
13030
+ const seq = Number(raw);
13031
+ return Number.isFinite(seq) ? Math.floor(seq) : 0;
13032
+ }
13033
+
13034
+ function normalizeRemoteFleetFramePayload(payload, fallbackKind = 'thumbnail') {
13035
+ if (!payload || typeof payload !== 'object') {
13036
+ return null;
13037
+ }
13038
+
13039
+ const frame = payload.frame || payload.Frame || payload;
13040
+ if (!frame || typeof frame !== 'object') {
13041
+ return null;
13042
+ }
13043
+
13044
+ const source = String(
13045
+ readRemoteFleetObjectField(frame, 'frameUrl', 'FrameUrl', '')
13046
+ || readRemoteFleetObjectField(frame, 'framePath', 'FramePath', '')
13047
+ || readRemoteFleetObjectField(frame, 'dataUrl', 'DataUrl', '')).trim();
13048
+ if (!isRemoteFleetFrameSource(source)) {
13049
+ return null;
13050
+ }
13051
+
13052
+ const seq = Number(readRemoteFleetObjectField(frame, 'frameSeq', 'FrameSeq', 0));
13053
+ return {
13054
+ deviceId: String(readRemoteFleetObjectField(frame, 'deviceId', 'DeviceId', '')).trim(),
13055
+ kind: String(readRemoteFleetObjectField(frame, 'kind', 'Kind', fallbackKind) || fallbackKind).trim().toLowerCase(),
13056
+ frameSeq: Number.isFinite(seq) ? Math.floor(seq) : 0,
13057
+ frameUrl: source,
13058
+ receivedAt: String(readRemoteFleetObjectField(frame, 'receivedAt', 'ReceivedAt', '') || '').trim(),
13059
+ capturedAt: String(readRemoteFleetObjectField(frame, 'capturedAt', 'CapturedAt', '') || '').trim(),
13060
+ streamId: String(readRemoteFleetObjectField(frame, 'streamId', 'StreamId', '') || '').trim()
13061
+ };
13062
+ }
13063
+
13064
+ function normalizeRemoteFleetDeviceFramePatches(result) {
13065
+ const rows = result?.frames || result?.Frames || [];
13066
+ if (!Array.isArray(rows)) {
13067
+ return [];
13068
+ }
13069
+
13070
+ const patches = [];
13071
+ rows.forEach(row => {
13072
+ const deviceId = String(readRemoteFleetObjectField(row, 'deviceId', 'DeviceId', '') || '').trim();
13073
+ const live = normalizeRemoteFleetFramePayload(row?.live || row?.Live, 'live');
13074
+ const thumbnail = normalizeRemoteFleetFramePayload(row?.thumbnail || row?.Thumbnail, 'thumbnail');
13075
+ [thumbnail, live].forEach(frame => {
13076
+ if (!frame) return;
13077
+ frame.deviceId = frame.deviceId || deviceId;
13078
+ patches.push(frame);
13079
+ });
13080
+ });
13081
+ return patches;
13082
+ }
13083
+
13084
+ function ensureRemoteFleetFrameImage(preview, frame) {
13085
+ let image = preview?.querySelector?.('img[data-remote-fleet-frame-image="true"]');
13086
+ if (image) {
13087
+ return image;
13088
+ }
13089
+
13090
+ image = document.createElement('img');
13091
+ image.dataset.remoteFleetFrameImage = 'true';
13092
+ image.alt = frame.kind === 'live' ? 'Live screen' : 'Remote screen';
13093
+ image.loading = frame.kind === 'thumbnail' ? 'lazy' : 'eager';
13094
+ image.decoding = 'async';
13095
+ image.style.cssText = 'width:100%;height:100%;object-fit:cover;display:block;';
13096
+ const placeholder = preview?.querySelector?.('[data-remote-fleet-screen-placeholder="true"]');
13097
+ if (placeholder) {
13098
+ placeholder.remove();
13099
+ }
13100
+ preview?.insertBefore?.(image, preview.firstChild || null);
13101
+ return image;
13102
+ }
13103
+
13104
+ function applyRemoteFleetFramePatchToPreview(preview, frame) {
13105
+ if (!preview || !frame || !isRemoteFleetFrameSource(frame.frameUrl)) {
13106
+ return false;
13107
+ }
13108
+
13109
+ const currentSeq = Number(preview.dataset.remoteFleetFrameSeq || '0');
13110
+ const nextSeq = Number(frame.frameSeq || 0);
13111
+ const currentKind = String(preview.dataset.remoteFleetFrameKind || '').toLowerCase();
13112
+ const isNewer = frame.kind === 'live' && currentKind !== 'live'
13113
+ || !Number.isFinite(currentSeq)
13114
+ || nextSeq <= 0
13115
+ || nextSeq > currentSeq
13116
+ || String(preview.dataset.remoteFleetFrameUrl || '') !== frame.frameUrl;
13117
+ if (!isNewer) {
13118
+ return false;
13119
+ }
13120
+
13121
+ const image = ensureRemoteFleetFrameImage(preview, frame);
13122
+ if (!image) {
13123
+ return false;
13124
+ }
13125
+
13126
+ image.dataset.remoteFleetFrameKind = frame.kind;
13127
+ image.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13128
+ image.dataset.remoteFleetFrameUrl = frame.frameUrl;
13129
+ image.loading = frame.kind === 'thumbnail' ? 'lazy' : 'eager';
13130
+ if (image.src !== frame.frameUrl) {
13131
+ image.src = frame.frameUrl;
13132
+ }
13133
+
13134
+ preview.dataset.remoteFleetFrameKind = frame.kind;
13135
+ preview.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13136
+ preview.dataset.remoteFleetFrameUrl = frame.frameUrl;
13137
+ preview.dataset.remoteFleetFrameAt = frame.receivedAt || frame.capturedAt || '';
13138
+
13139
+ const badge = preview.querySelector('[data-remote-fleet-frame-badge="true"]');
13140
+ if (badge) {
13141
+ const at = frame.receivedAt || frame.capturedAt || '';
13142
+ badge.textContent = frame.kind === 'live'
13143
+ ? `LIVE ${at ? formatRemoteFleetAge(at) : ''}`.trim()
13144
+ : (at ? formatRemoteFleetAge(at) : 'Screen');
13145
+ badge.style.display = 'inline-flex';
13146
+ badge.style.background = frame.kind === 'live'
13147
+ ? 'rgba(220, 38, 38, 0.84)'
13148
+ : 'rgba(15, 23, 42, 0.72)';
13149
+ }
13150
+
13151
+ return true;
13152
+ }
13153
+
13154
+ function applyRemoteFleetFramePatches(bodyView, patches) {
13155
+ if (!bodyView || !Array.isArray(patches) || patches.length === 0) {
13156
+ return 0;
13157
+ }
13158
+
13159
+ let applied = 0;
13160
+ patches.forEach(frame => {
13161
+ const deviceId = String(frame?.deviceId || '').trim();
13162
+ if (!deviceId) return;
13163
+
13164
+ bodyView.querySelectorAll('[data-remote-fleet-device-preview][data-device-id]').forEach(preview => {
13165
+ if (String(preview.dataset.deviceId || '').trim() !== deviceId) return;
13166
+ const currentKind = String(preview.dataset.remoteFleetFrameKind || '').toLowerCase();
13167
+ if (currentKind === 'live' && frame.kind !== 'live') return;
13168
+ if (applyRemoteFleetFramePatchToPreview(preview, frame)) {
13169
+ applied += 1;
13170
+ }
13171
+ });
13172
+
13173
+ bodyView.querySelectorAll(`article[data-device-id]`).forEach(card => {
13174
+ if (String(card.dataset.deviceId || '').trim() === deviceId && frame.kind) {
13175
+ card.dataset.remoteFleetHasFrame = 'true';
13176
+ }
13177
+ });
13178
+ });
13179
+
13180
+ if (applied > 0) {
13181
+ window.RuntimeTrace?.emit?.('remote.frame.uiPatched', {
13182
+ count: applied
13183
+ });
13184
+ }
13185
+
13186
+ return applied;
13187
+ }
13188
+
13189
+ function startRemoteFleetFrameLoop(bodyView, intervalMs, refreshCallback) {
13190
+ if (!bodyView || typeof refreshCallback !== 'function') {
13191
+ return;
13192
+ }
13193
+
13194
+ bodyView._remoteFleetFrameLoopActive = true;
13195
+ let lastTick = 0;
13196
+ const loop = timestamp => {
13197
+ if (!bodyView._remoteFleetFrameLoopActive || !document.body.contains(bodyView)) {
13198
+ clearRemoteFleetTimers(bodyView);
13199
+ return;
13200
+ }
13201
+
13202
+ if (timestamp - lastTick >= intervalMs && bodyView._remoteFleetFrameRefreshInFlight !== true) {
13203
+ lastTick = timestamp;
13204
+ bodyView._remoteFleetFrameRefreshInFlight = true;
13205
+ Promise.resolve(refreshCallback())
13206
+ .catch(() => {
13207
+ clearRemoteFleetTimers(bodyView);
13208
+ })
13209
+ .finally(() => {
13210
+ bodyView._remoteFleetFrameRefreshInFlight = false;
13211
+ });
13212
+ }
13213
+
13214
+ bodyView._remoteFleetFrameLoopRaf = requestRemoteFleetFrameLoopFrame(loop);
13215
+ };
13216
+
13217
+ bodyView._remoteFleetFrameLoopRaf = requestRemoteFleetFrameLoopFrame(loop);
13218
+ }
13219
+
12986
13220
  function isRemoteFleetLiveActive(device) {
12987
13221
  return getRemoteFleetDeviceField(device, 'liveStreamActive', 'LiveStreamActive', false) === true;
12988
13222
  }
@@ -13215,6 +13449,15 @@
13215
13449
  bodyView._remoteFleetRefreshInFlight = false;
13216
13450
  }
13217
13451
  };
13452
+ const refreshRemoteDeviceFrame = async (kind = 'live') => {
13453
+ const result = await invokeDotNetAsync('GetRemoteFleetFrameFromJs', nodeId, deviceId, kind);
13454
+ const frame = normalizeRemoteFleetFramePayload(result?.frame || result?.Frame, kind);
13455
+ if (frame) {
13456
+ frame.deviceId = frame.deviceId || deviceId;
13457
+ applyRemoteFleetFramePatches(bodyView, [frame]);
13458
+ }
13459
+ return result;
13460
+ };
13218
13461
 
13219
13462
  if (!device || !deviceId) {
13220
13463
  const empty = document.createElement('div');
@@ -13314,6 +13557,12 @@
13314
13557
  bodyView.appendChild(header);
13315
13558
 
13316
13559
  const preview = document.createElement('div');
13560
+ preview.dataset.remoteFleetDevicePreview = 'pinned';
13561
+ preview.dataset.deviceId = deviceId;
13562
+ preview.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : (hasThumbnail ? 'thumbnail' : '');
13563
+ preview.dataset.remoteFleetFrameSeq = String(hasLiveFrame
13564
+ ? getRemoteFleetDeviceField(device, 'liveFrameSeq', 'LiveFrameSeq', 0)
13565
+ : getRemoteFleetDeviceField(device, 'thumbnailFrameSeq', 'ThumbnailFrameSeq', 0));
13317
13566
  preview.style.cssText = `
13318
13567
  position: relative;
13319
13568
  flex: 0 0 auto;
@@ -13326,6 +13575,9 @@
13326
13575
  `;
13327
13576
  if (hasLiveFrame || hasThumbnail) {
13328
13577
  const image = document.createElement('img');
13578
+ image.dataset.remoteFleetFrameImage = 'true';
13579
+ image.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : 'thumbnail';
13580
+ image.dataset.remoteFleetFrameSeq = preview.dataset.remoteFleetFrameSeq;
13329
13581
  image.src = previewSource;
13330
13582
  image.alt = `${name} screen`;
13331
13583
  image.loading = 'lazy';
@@ -13334,6 +13586,7 @@
13334
13586
  preview.appendChild(image);
13335
13587
  } else {
13336
13588
  const placeholder = document.createElement('div');
13589
+ placeholder.dataset.remoteFleetScreenPlaceholder = 'true';
13337
13590
  placeholder.textContent = thumbnailEnabled ? 'No frame yet' : 'Status only';
13338
13591
  placeholder.style.cssText = `
13339
13592
  position: absolute;
@@ -13349,6 +13602,7 @@
13349
13602
  preview.appendChild(placeholder);
13350
13603
  }
13351
13604
  const previewBadge = document.createElement('span');
13605
+ previewBadge.dataset.remoteFleetFrameBadge = 'true';
13352
13606
  previewBadge.textContent = hasLiveFrame
13353
13607
  ? `LIVE ${previewAt ? formatRemoteFleetAge(previewAt) : ''}`.trim()
13354
13608
  : (previewAt ? formatRemoteFleetAge(previewAt) : (hubStatus === 'online' ? 'Pinned' : 'Hub offline'));
@@ -13627,6 +13881,7 @@
13627
13881
  });
13628
13882
 
13629
13883
  if (liveActive) {
13884
+ startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS, () => refreshRemoteDeviceFrame('live'));
13630
13885
  bodyView._remoteFleetLiveRefreshTimer = setInterval(async () => {
13631
13886
  if (!document.body.contains(bodyView)) {
13632
13887
  clearRemoteFleetTimers(bodyView);
@@ -14141,6 +14396,10 @@
14141
14396
  `;
14142
14397
 
14143
14398
  const livePreview = document.createElement('div');
14399
+ livePreview.dataset.remoteFleetDevicePreview = 'focused-live';
14400
+ livePreview.dataset.deviceId = focusedId;
14401
+ livePreview.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : '';
14402
+ livePreview.dataset.remoteFleetFrameSeq = String(getRemoteFleetDeviceField(focusedDevice, 'liveFrameSeq', 'LiveFrameSeq', 0));
14144
14403
  livePreview.style.cssText = `
14145
14404
  position: relative;
14146
14405
  min-width: 0;
@@ -14152,6 +14411,9 @@
14152
14411
  `;
14153
14412
  if (hasLiveFrame) {
14154
14413
  const image = document.createElement('img');
14414
+ image.dataset.remoteFleetFrameImage = 'true';
14415
+ image.dataset.remoteFleetFrameKind = 'live';
14416
+ image.dataset.remoteFleetFrameSeq = livePreview.dataset.remoteFleetFrameSeq;
14155
14417
  image.src = liveFrameSource;
14156
14418
  image.alt = `${focusedName} live screen`;
14157
14419
  image.decoding = 'async';
@@ -14164,6 +14426,7 @@
14164
14426
  livePreview.appendChild(image);
14165
14427
  } else {
14166
14428
  const placeholder = document.createElement('div');
14429
+ placeholder.dataset.remoteFleetScreenPlaceholder = 'true';
14167
14430
  placeholder.textContent = liveActive ? 'Waiting for live frame' : 'Live view idle';
14168
14431
  placeholder.style.cssText = `
14169
14432
  position: absolute;
@@ -14179,6 +14442,7 @@
14179
14442
  livePreview.appendChild(placeholder);
14180
14443
  }
14181
14444
  const liveBadge = document.createElement('span');
14445
+ liveBadge.dataset.remoteFleetFrameBadge = 'true';
14182
14446
  liveBadge.textContent = liveActive
14183
14447
  ? `LIVE ${liveFrameAt ? formatRemoteFleetAge(liveFrameAt) : ''}`.trim()
14184
14448
  : 'FOCUS';
@@ -14267,6 +14531,11 @@
14267
14531
 
14268
14532
  const preview = document.createElement('div');
14269
14533
  preview.dataset.remoteFleetDevicePreview = mode;
14534
+ preview.dataset.deviceId = getRemoteFleetDeviceId(device);
14535
+ preview.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : (hasThumbnail ? 'thumbnail' : '');
14536
+ preview.dataset.remoteFleetFrameSeq = String(hasLiveFrame
14537
+ ? getRemoteFleetDeviceField(device, 'liveFrameSeq', 'LiveFrameSeq', 0)
14538
+ : getRemoteFleetDeviceField(device, 'thumbnailFrameSeq', 'ThumbnailFrameSeq', 0));
14270
14539
  preview.style.cssText = `
14271
14540
  position: relative;
14272
14541
  width: 100%;
@@ -14279,6 +14548,9 @@
14279
14548
 
14280
14549
  if (hasLiveFrame || hasThumbnail) {
14281
14550
  const image = document.createElement('img');
14551
+ image.dataset.remoteFleetFrameImage = 'true';
14552
+ image.dataset.remoteFleetFrameKind = hasLiveFrame ? 'live' : 'thumbnail';
14553
+ image.dataset.remoteFleetFrameSeq = preview.dataset.remoteFleetFrameSeq;
14282
14554
  image.src = previewSource;
14283
14555
  image.alt = hasLiveFrame ? `${name} live frame` : `${name} thumbnail`;
14284
14556
  image.loading = 'lazy';
@@ -14316,6 +14588,7 @@
14316
14588
 
14317
14589
  if (hasLiveFrame || (isDetail && previewAt)) {
14318
14590
  const badge = document.createElement('span');
14591
+ badge.dataset.remoteFleetFrameBadge = 'true';
14319
14592
  badge.textContent = hasLiveFrame
14320
14593
  ? (isDetail && previewAt ? `LIVE ${formatRemoteFleetAge(previewAt)}` : 'LIVE')
14321
14594
  : formatRemoteFleetAge(previewAt);
@@ -14738,6 +15011,19 @@
14738
15011
  const readTaskInstruction = () => String(taskInput.value || '').trim();
14739
15012
  const useAiAssist = () => aiToggle.checked === true;
14740
15013
  const getDeviceCards = () => Array.from(grid.querySelectorAll('article[data-device-id]'));
15014
+ const getVisibleFrameDeviceIds = () => {
15015
+ const ids = getDeviceCards()
15016
+ .filter(card => card.style.display !== 'none')
15017
+ .map(card => String(card.dataset.deviceId || '').trim())
15018
+ .filter(Boolean);
15019
+ if (focusedDevice) {
15020
+ const focusedId = getRemoteFleetDeviceId(focusedDevice);
15021
+ if (focusedId) {
15022
+ ids.unshift(focusedId);
15023
+ }
15024
+ }
15025
+ return Array.from(new Set(ids)).slice(0, 120);
15026
+ };
14741
15027
  const refreshRemoteFleetNode = async () => {
14742
15028
  if (bodyView._remoteFleetRefreshInFlight === true) {
14743
15029
  return null;
@@ -14752,6 +15038,11 @@
14752
15038
  bodyView._remoteFleetRefreshInFlight = false;
14753
15039
  }
14754
15040
  };
15041
+ const refreshRemoteFleetVisibleFrames = async (requestThumbnails = false) => {
15042
+ const result = await invokeDotNetAsync('RefreshRemoteFleetFramesFromJs', nodeId, getVisibleFrameDeviceIds(), requestThumbnails === true);
15043
+ applyRemoteFleetFramePatches(bodyView, normalizeRemoteFleetDeviceFramePatches(result));
15044
+ return result;
15045
+ };
14755
15046
  const prepareRemoteFleetTaskFollow = batch => {
14756
15047
  if (!isRemoteFleetTaskBatchActive(batch)) {
14757
15048
  bodyView.dataset.remoteFleetTaskFollowActive = 'false';
@@ -15023,6 +15314,7 @@
15023
15314
 
15024
15315
  const setRemoteFleetHostTarget = async (enabled, options = {}) => {
15025
15316
  const quiet = options?.quiet === true;
15317
+ const renew = options?.renew === true || quiet;
15026
15318
  const activeButton = enabled ? hostButton : stopHostButton;
15027
15319
  if (!quiet && activeButton) {
15028
15320
  activeButton.disabled = true;
@@ -15032,10 +15324,11 @@
15032
15324
  setTaskFeedback(enabled ? 'Setting host target...' : 'Stopping host target...');
15033
15325
  }
15034
15326
  try {
15035
- const result = await invokeDotNetAsync('SetRemoteFleetHostFromJs', nodeId, enabled === true);
15327
+ const result = await invokeDotNetAsync('SetRemoteFleetHostFromJs', nodeId, enabled === true, renew === true);
15036
15328
  window.RuntimeTrace?.emit?.('remote.hostTarget.result', {
15037
15329
  nodeId,
15038
15330
  enabled: enabled === true,
15331
+ renew: renew === true,
15039
15332
  success: isRemoteFleetResultSuccess(result),
15040
15333
  active: isRemoteFleetResultActive(result),
15041
15334
  error: result?.error || result?.Error || ''
@@ -15043,6 +15336,9 @@
15043
15336
  rememberRemoteFleetLocalHostTarget(nodeId, enabled === true, result);
15044
15337
  await syncRemoteFleetNodeStateFromResult(result);
15045
15338
  if (quiet) {
15339
+ if (!isRemoteFleetResultSuccess(result) || !isRemoteFleetResultActive(result)) {
15340
+ stopRemoteFleetHostLeaseTimer(nodeId);
15341
+ }
15046
15342
  return result;
15047
15343
  }
15048
15344
  if (isRemoteFleetResultSuccess(result) && enabled !== true) {
@@ -15205,10 +15501,11 @@
15205
15501
  });
15206
15502
 
15207
15503
  if (isHostingTarget) {
15208
- startRemoteFleetHostLeaseTimer(nodeId, () => setRemoteFleetHostTarget(true, { quiet: true }));
15504
+ startRemoteFleetHostLeaseTimer(nodeId, () => setRemoteFleetHostTarget(true, { quiet: true, renew: true }));
15209
15505
  }
15210
15506
 
15211
15507
  if (hasActiveLiveStream) {
15508
+ startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS, () => refreshRemoteFleetVisibleFrames(false));
15212
15509
  bodyView._remoteFleetLiveRefreshTimer = setInterval(async () => {
15213
15510
  if (!document.body.contains(bodyView)) {
15214
15511
  clearRemoteFleetTimers(bodyView);
@@ -15222,6 +15519,7 @@
15222
15519
  }
15223
15520
  }, REMOTE_FLEET_LIVE_REFRESH_MS);
15224
15521
  } else if (autoMonitorState && hasMonitorTargets) {
15522
+ startRemoteFleetFrameLoop(bodyView, REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS, () => refreshRemoteFleetVisibleFrames(true));
15225
15523
  bodyView._remoteFleetMonitorRefreshTimer = setInterval(async () => {
15226
15524
  if (!document.body.contains(bodyView)) {
15227
15525
  clearRemoteFleetTimers(bodyView);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "mainAssemblyName": "MindExecution.Web",
3
3
  "resources": {
4
- "hash": "sha256-9/5POBUnUjRLHnaTUce3v/cfR0oqf0jzjsZLKmmaF9k=",
4
+ "hash": "sha256-FI1aVvJXZHMtJ4l634osWbTe8sQ5rfdCKfSBgDnqQ70=",
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.brmz7yk5qh.dll": "System.dll",
124
124
  "netstandard.yvr3prsx0x.dll": "netstandard.dll",
125
125
  "System.Private.CoreLib.ns29bor93l.dll": "System.Private.CoreLib.dll",
126
- "MindExecution.Core.fv9epd367q.dll": "MindExecution.Core.dll",
127
- "MindExecution.Kernel.necgouk2lu.dll": "MindExecution.Kernel.dll",
128
- "MindExecution.Plugins.Admin.i1bsxgnkwb.dll": "MindExecution.Plugins.Admin.dll",
129
- "MindExecution.Plugins.Business.opnf5esnox.dll": "MindExecution.Plugins.Business.dll",
130
- "MindExecution.Plugins.Concept.3c5vvjh1ax.dll": "MindExecution.Plugins.Concept.dll",
131
- "MindExecution.Plugins.Directory.mcs5ilkrby.dll": "MindExecution.Plugins.Directory.dll",
132
- "MindExecution.Plugins.PlanMaster.ofkqkx5csm.dll": "MindExecution.Plugins.PlanMaster.dll",
133
- "MindExecution.Plugins.YouTube.si9ylbnkqo.dll": "MindExecution.Plugins.YouTube.dll",
134
- "MindExecution.Shared.w5v05uuccd.dll": "MindExecution.Shared.dll",
135
- "MindExecution.Web.y71txqhdir.dll": "MindExecution.Web.dll",
126
+ "MindExecution.Core.fu1rl67yt3.dll": "MindExecution.Core.dll",
127
+ "MindExecution.Kernel.cqcbagjpqb.dll": "MindExecution.Kernel.dll",
128
+ "MindExecution.Plugins.Admin.tsn0j478un.dll": "MindExecution.Plugins.Admin.dll",
129
+ "MindExecution.Plugins.Business.xg74dmn0vz.dll": "MindExecution.Plugins.Business.dll",
130
+ "MindExecution.Plugins.Concept.j0zntvuecv.dll": "MindExecution.Plugins.Concept.dll",
131
+ "MindExecution.Plugins.Directory.9i4bd043ia.dll": "MindExecution.Plugins.Directory.dll",
132
+ "MindExecution.Plugins.PlanMaster.vml3qie2ji.dll": "MindExecution.Plugins.PlanMaster.dll",
133
+ "MindExecution.Plugins.YouTube.0gfbwq1jfg.dll": "MindExecution.Plugins.YouTube.dll",
134
+ "MindExecution.Shared.f3bclzo6k4.dll": "MindExecution.Shared.dll",
135
+ "MindExecution.Web.4jhsxoiqgz.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",
@@ -278,18 +278,18 @@
278
278
  "System.Xml.XDocument.sn51jas17n.dll": "sha256-GNI2kFgFmPTwzuzwUn8gxK+AzGLUWRJFdg9JzIbrybQ=",
279
279
  "System.brmz7yk5qh.dll": "sha256-CfM2miyj1KHApFmqMdLYWio3S/jrdON2pW9Xr2nTwlo=",
280
280
  "netstandard.yvr3prsx0x.dll": "sha256-EksNn8Luo4bOWqJ6X7dIe9qG9oOqwOVzjH2xYyMNi+E=",
281
- "MindExecution.Core.fv9epd367q.dll": "sha256-e+bWfgea05kkjqA0d7SoScYnRUTDwrAa8jGcE/9efgM=",
282
- "MindExecution.Kernel.necgouk2lu.dll": "sha256-MU33gJtnXnCTK0arVlYP8NdKUNQmQCeew/ywgj2tgvA=",
283
- "MindExecution.Plugins.Concept.3c5vvjh1ax.dll": "sha256-wyfXidn4Mwhv1tdPa/Zg2SA6siukk/wKFM5m4njh5Fk=",
284
- "MindExecution.Plugins.PlanMaster.ofkqkx5csm.dll": "sha256-9PE8rjbSnD0GOryMtJHtpn5riVUL5GdBFDxDTXp4rqM=",
285
- "MindExecution.Shared.w5v05uuccd.dll": "sha256-xNquLGF4gJlatw7ttFI6XIhlRHGjfcYPAKQLxbrpA60=",
286
- "MindExecution.Web.y71txqhdir.dll": "sha256-bmQOJzNyNjQHR3e5FXnYm2vV7vU8U/EzqTJlJ4KwcGo="
281
+ "MindExecution.Core.fu1rl67yt3.dll": "sha256-6cDbehKdjX71zeL9Ro5GNupn7wqRYfb7yLW2w3Wp05g=",
282
+ "MindExecution.Kernel.cqcbagjpqb.dll": "sha256-zPB0tmwi/UKdJ//g0xMH1Y02ahDX5ii6ZKdB3yiQQz4=",
283
+ "MindExecution.Plugins.Concept.j0zntvuecv.dll": "sha256-/XUaopvgQk71o+jBdb3ljhCAQkXrda6XxCzS0242pIo=",
284
+ "MindExecution.Plugins.PlanMaster.vml3qie2ji.dll": "sha256-uS3p/j4Kq171sz/xkiEn08DZni3X6HLbq2OHsYcxIjg=",
285
+ "MindExecution.Shared.f3bclzo6k4.dll": "sha256-1ZuF0eTN8dm8o0BzDJX+lyuKB1Wlc8MO2+kPJx/TYec=",
286
+ "MindExecution.Web.4jhsxoiqgz.dll": "sha256-QPegscpX6rm9Fp7lPqHdeKDVUFshfip6frFo62NWuss="
287
287
  },
288
288
  "lazyAssembly": {
289
- "MindExecution.Plugins.Admin.i1bsxgnkwb.dll": "sha256-5pd/Pw8FqxoZ/PqvlOz4EJuXGLmmTggZYpYjpj3chjA=",
290
- "MindExecution.Plugins.Business.opnf5esnox.dll": "sha256-ND2mM989Ka3iOmyVqQtXkMVkR74oGR67uenBuStXGTA=",
291
- "MindExecution.Plugins.Directory.mcs5ilkrby.dll": "sha256-xuSRgmxlBfx2qx0YiiyxrAvD6S5XKJrCdfxRCOWloqY=",
292
- "MindExecution.Plugins.YouTube.si9ylbnkqo.dll": "sha256-TOoWWas3rXuwWEVbujJUco7sNB8P/fS4k2yB0Vqs0AY="
289
+ "MindExecution.Plugins.Admin.tsn0j478un.dll": "sha256-g5Q4Ihy2PJKx6EFB6k78dIszLgK4hZ3Xintjvso/zmw=",
290
+ "MindExecution.Plugins.Business.xg74dmn0vz.dll": "sha256-0bP/QgMyXSk9IlQVun63rnWvkwqqZmJcRe90QoPC6jw=",
291
+ "MindExecution.Plugins.Directory.9i4bd043ia.dll": "sha256-b+fpVz2RkQC8uL4dIvN6wMWWefoII84Jyfe85EU/URk=",
292
+ "MindExecution.Plugins.YouTube.0gfbwq1jfg.dll": "sha256-EEXiqTRw/mDzke0TaI/QAlp2DRCQCfL4lzGSH0pRZ4c="
293
293
  }
294
294
  },
295
295
  "cacheBootResources": true,
@@ -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=20260614-remote-registry-v511" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260614-remote-registry-v511" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260614-remote-frame-meta-v513" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260614-remote-frame-meta-v513" />
12
12
  <!-- ?쇄뼹??Font Awesome (local) ?쇄뼹??-->
13
13
  <link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
14
14
  <!-- ?꿎뼯??-->
@@ -558,7 +558,7 @@
558
558
  }
559
559
 
560
560
  const base = '_content/MindExecution.Shared/js/';
561
- const scriptVersion = '20260614-remote-registry-v511';
561
+ const scriptVersion = '20260614-remote-frame-meta-v513';
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": "Mphxacza",
2
+ "version": "3rReX/U0",
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-2LFL3oGey+usyB7lpywzpKYMhBmlMhrXi9IZdtdUJZU=",
89
+ "hash": "sha256-U5R3dUgCFR7qo8wM4p3MlIDxa9ZCd686fnrWvQFfSfs=",
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-e+bWfgea05kkjqA0d7SoScYnRUTDwrAa8jGcE/9efgM=",
414
- "url": "_framework/MindExecution.Core.fv9epd367q.dll"
413
+ "hash": "sha256-6cDbehKdjX71zeL9Ro5GNupn7wqRYfb7yLW2w3Wp05g=",
414
+ "url": "_framework/MindExecution.Core.fu1rl67yt3.dll"
415
415
  },
416
416
  {
417
- "hash": "sha256-MU33gJtnXnCTK0arVlYP8NdKUNQmQCeew/ywgj2tgvA=",
418
- "url": "_framework/MindExecution.Kernel.necgouk2lu.dll"
417
+ "hash": "sha256-zPB0tmwi/UKdJ//g0xMH1Y02ahDX5ii6ZKdB3yiQQz4=",
418
+ "url": "_framework/MindExecution.Kernel.cqcbagjpqb.dll"
419
419
  },
420
420
  {
421
- "hash": "sha256-5pd/Pw8FqxoZ/PqvlOz4EJuXGLmmTggZYpYjpj3chjA=",
422
- "url": "_framework/MindExecution.Plugins.Admin.i1bsxgnkwb.dll"
421
+ "hash": "sha256-g5Q4Ihy2PJKx6EFB6k78dIszLgK4hZ3Xintjvso/zmw=",
422
+ "url": "_framework/MindExecution.Plugins.Admin.tsn0j478un.dll"
423
423
  },
424
424
  {
425
- "hash": "sha256-ND2mM989Ka3iOmyVqQtXkMVkR74oGR67uenBuStXGTA=",
426
- "url": "_framework/MindExecution.Plugins.Business.opnf5esnox.dll"
425
+ "hash": "sha256-0bP/QgMyXSk9IlQVun63rnWvkwqqZmJcRe90QoPC6jw=",
426
+ "url": "_framework/MindExecution.Plugins.Business.xg74dmn0vz.dll"
427
427
  },
428
428
  {
429
- "hash": "sha256-wyfXidn4Mwhv1tdPa/Zg2SA6siukk/wKFM5m4njh5Fk=",
430
- "url": "_framework/MindExecution.Plugins.Concept.3c5vvjh1ax.dll"
429
+ "hash": "sha256-/XUaopvgQk71o+jBdb3ljhCAQkXrda6XxCzS0242pIo=",
430
+ "url": "_framework/MindExecution.Plugins.Concept.j0zntvuecv.dll"
431
431
  },
432
432
  {
433
- "hash": "sha256-xuSRgmxlBfx2qx0YiiyxrAvD6S5XKJrCdfxRCOWloqY=",
434
- "url": "_framework/MindExecution.Plugins.Directory.mcs5ilkrby.dll"
433
+ "hash": "sha256-b+fpVz2RkQC8uL4dIvN6wMWWefoII84Jyfe85EU/URk=",
434
+ "url": "_framework/MindExecution.Plugins.Directory.9i4bd043ia.dll"
435
435
  },
436
436
  {
437
- "hash": "sha256-9PE8rjbSnD0GOryMtJHtpn5riVUL5GdBFDxDTXp4rqM=",
438
- "url": "_framework/MindExecution.Plugins.PlanMaster.ofkqkx5csm.dll"
437
+ "hash": "sha256-uS3p/j4Kq171sz/xkiEn08DZni3X6HLbq2OHsYcxIjg=",
438
+ "url": "_framework/MindExecution.Plugins.PlanMaster.vml3qie2ji.dll"
439
439
  },
440
440
  {
441
- "hash": "sha256-TOoWWas3rXuwWEVbujJUco7sNB8P/fS4k2yB0Vqs0AY=",
442
- "url": "_framework/MindExecution.Plugins.YouTube.si9ylbnkqo.dll"
441
+ "hash": "sha256-EEXiqTRw/mDzke0TaI/QAlp2DRCQCfL4lzGSH0pRZ4c=",
442
+ "url": "_framework/MindExecution.Plugins.YouTube.0gfbwq1jfg.dll"
443
443
  },
444
444
  {
445
- "hash": "sha256-xNquLGF4gJlatw7ttFI6XIhlRHGjfcYPAKQLxbrpA60=",
446
- "url": "_framework/MindExecution.Shared.w5v05uuccd.dll"
445
+ "hash": "sha256-1ZuF0eTN8dm8o0BzDJX+lyuKB1Wlc8MO2+kPJx/TYec=",
446
+ "url": "_framework/MindExecution.Shared.f3bclzo6k4.dll"
447
447
  },
448
448
  {
449
- "hash": "sha256-bmQOJzNyNjQHR3e5FXnYm2vV7vU8U/EzqTJlJ4KwcGo=",
450
- "url": "_framework/MindExecution.Web.y71txqhdir.dll"
449
+ "hash": "sha256-QPegscpX6rm9Fp7lPqHdeKDVUFshfip6frFo62NWuss=",
450
+ "url": "_framework/MindExecution.Web.4jhsxoiqgz.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-Dp7hmEZrcfmwHqq9wTzyrgD8uX+Rjk/Nca/UfWIO0ao=",
773
+ "hash": "sha256-XdUGtIDw1SDDWXPLtg2RaeuvCW6T6yjMxok5H9KUFaE=",
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-UcE/wpl6GRqeR7eg9lYKHo6tvWbqZSMb//rVca+L8qg=",
837
+ "hash": "sha256-KqDHFUlmca/5qM/MGimpiIQKNxh1Udxo7/O1bDIsk+s=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: Mphxacza */
1
+ /* Manifest version: 3rReX/U0 */
2
2
  // Hosted deployments should prefer the network over stale offline caches.
3
3
  // This service worker immediately clears old Blazor offline caches and unregisters itself.
4
4