@mindexec/cli 0.2.115 → 0.2.116

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindexec/cli",
3
- "version": "0.2.115",
3
+ "version": "0.2.116",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -170,7 +170,7 @@ async function main() {
170
170
  const framePromise = waitForBinaryFrame(ws);
171
171
  const live = await fetchJson(`${bridge.baseUrl}/api/remote/devices/${encodeURIComponent(device.deviceId)}/live/start`, {
172
172
  method: 'POST',
173
- body: JSON.stringify({ fps: 10 })
173
+ body: JSON.stringify({ fps: 20 })
174
174
  });
175
175
  assert.equal(live.ok, true);
176
176
 
@@ -178,6 +178,7 @@ async function main() {
178
178
  assert.equal(frame.metadata.type, 'remote.frame.binary');
179
179
  assert.equal(frame.metadata.kind, 'live');
180
180
  assert.equal(frame.metadata.deviceId, device.deviceId);
181
+ assert.equal(frame.metadata.fps, 20);
181
182
  assert.ok(frame.metadata.frameSeq > 0, 'frameSeq should be positive');
182
183
  assert.equal(frame.metadata.mimeType, 'image/png');
183
184
  assert.ok(frame.payload.length > 0, 'payload should be non-empty');
@@ -5,7 +5,7 @@
5
5
  const DEBUG = false;
6
6
  const FPS_DEBUG = false;
7
7
  const FRAME_PERF_DEBUG = false;
8
- const MINDMAP_CORE_BUILD_ID = '20260616-remote-ws-binary-frames-v572';
8
+ const MINDMAP_CORE_BUILD_ID = '20260616-remote-ws-control-frames-v573';
9
9
  const CanvasPhase = Object.freeze({
10
10
  Booting: 'booting',
11
11
  BoardFileLoading: 'board-file-loading',
@@ -13345,6 +13345,8 @@
13345
13345
  const REMOTE_FLEET_LIVE_REFRESH_MS = 30000;
13346
13346
  const REMOTE_FLEET_MONITOR_LIVE_FPS = 10;
13347
13347
  const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = Math.round(1000 / REMOTE_FLEET_MONITOR_LIVE_FPS);
13348
+ const REMOTE_FLEET_CONTROL_LIVE_FPS = 20;
13349
+ const REMOTE_FLEET_CONTROL_FRAME_REFRESH_MS = Math.round(1000 / REMOTE_FLEET_CONTROL_LIVE_FPS);
13348
13350
  const REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS = 2000;
13349
13351
  const REMOTE_FLEET_FRAME_CANVAS_MAX_DPR = 2;
13350
13352
  const REMOTE_FLEET_FRAME_BLOB_CACHE_MS = 10000;
@@ -13622,7 +13624,8 @@
13622
13624
 
13623
13625
  const payload = buffer.slice(4 + metaLength);
13624
13626
  const mimeType = String(metadata.mimeType || metadata.format || 'image/jpeg').trim() || 'image/jpeg';
13625
- const objectUrl = URL.createObjectURL(new Blob([payload], { type: mimeType }));
13627
+ const payloadBlob = new Blob([payload], { type: mimeType });
13628
+ const objectUrl = URL.createObjectURL(payloadBlob);
13626
13629
  return {
13627
13630
  ...metadata,
13628
13631
  kind: String(metadata.kind || 'live').toLowerCase() === 'thumbnail' ? 'thumbnail' : 'live',
@@ -13631,6 +13634,7 @@
13631
13634
  framePath: objectUrl,
13632
13635
  dataUrl: '',
13633
13636
  _remoteFleetObjectUrl: objectUrl,
13637
+ _remoteFleetPayloadBlob: payloadBlob,
13634
13638
  _remoteFleetBinaryFrame: true
13635
13639
  };
13636
13640
  }
@@ -13650,13 +13654,27 @@
13650
13654
  }
13651
13655
  }
13652
13656
 
13653
- function getRemoteFleetBinaryFrameDeviceIds(getDeviceIds) {
13657
+ function getRemoteFleetBinaryFrameDeviceIds(sessionOrGetter) {
13658
+ const getDeviceIds = typeof sessionOrGetter === 'function'
13659
+ ? sessionOrGetter
13660
+ : sessionOrGetter?.getDeviceIds;
13654
13661
  const ids = typeof getDeviceIds === 'function'
13655
13662
  ? getDeviceIds()
13656
13663
  : [];
13657
- return Array.from(new Set((Array.isArray(ids) ? ids : [])
13664
+ const normalized = (Array.isArray(ids) ? ids : [])
13658
13665
  .map(value => String(value || '').trim())
13659
- .filter(Boolean)))
13666
+ .filter(Boolean);
13667
+
13668
+ if (sessionOrGetter?.controlSessions instanceof Set) {
13669
+ sessionOrGetter.controlSessions.forEach(controlSession => {
13670
+ const deviceId = String(controlSession?.deviceId || '').trim();
13671
+ if (deviceId) {
13672
+ normalized.push(deviceId);
13673
+ }
13674
+ });
13675
+ }
13676
+
13677
+ return Array.from(new Set(normalized))
13660
13678
  .slice(0, 240);
13661
13679
  }
13662
13680
 
@@ -13665,7 +13683,7 @@
13665
13683
  return false;
13666
13684
  }
13667
13685
 
13668
- const deviceIds = getRemoteFleetBinaryFrameDeviceIds(session.getDeviceIds);
13686
+ const deviceIds = getRemoteFleetBinaryFrameDeviceIds(session);
13669
13687
  const key = deviceIds.join('\n');
13670
13688
  if (!force && session.subscriptionKey === key) {
13671
13689
  return true;
@@ -13681,7 +13699,7 @@
13681
13699
  }
13682
13700
 
13683
13701
  function scheduleRemoteFleetBinaryFrameReconnect(session) {
13684
- if (!session || session.reconnectTimer || session.bodies.size === 0) {
13702
+ if (!session || session.reconnectTimer || (session.bodies.size === 0 && (!session.controlSessions || session.controlSessions.size === 0))) {
13685
13703
  return;
13686
13704
  }
13687
13705
 
@@ -13692,7 +13710,7 @@
13692
13710
  }
13693
13711
 
13694
13712
  async function openRemoteFleetBinaryFrameSocket(session) {
13695
- if (!session || session.bodies.size === 0 || typeof WebSocket !== 'function') {
13713
+ if (!session || (session.bodies.size === 0 && (!session.controlSessions || session.controlSessions.size === 0)) || typeof WebSocket !== 'function') {
13696
13714
  return false;
13697
13715
  }
13698
13716
 
@@ -13733,7 +13751,7 @@
13733
13751
 
13734
13752
  parseRemoteFleetBinaryFrameMessage(event.data)
13735
13753
  .then(frame => {
13736
- if (!frame || session.bodies.size === 0) {
13754
+ if (!frame || (session.bodies.size === 0 && (!session.controlSessions || session.controlSessions.size === 0))) {
13737
13755
  if (frame?._remoteFleetObjectUrl && typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {
13738
13756
  URL.revokeObjectURL(frame._remoteFleetObjectUrl);
13739
13757
  }
@@ -13747,7 +13765,38 @@
13747
13765
  }
13748
13766
  });
13749
13767
 
13750
- if (applied <= 0 && frame._remoteFleetObjectUrl && typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {
13768
+ let controlPaintQueued = 0;
13769
+ if (session.controlSessions instanceof Set && session.controlSessions.size > 0) {
13770
+ session.controlSessions.forEach(controlSession => {
13771
+ if (!controlSession?.active) {
13772
+ session.controlSessions.delete(controlSession);
13773
+ return;
13774
+ }
13775
+
13776
+ if (String(controlSession.deviceId || '').trim() !== String(frame.deviceId || '').trim()) {
13777
+ return;
13778
+ }
13779
+
13780
+ controlPaintQueued += 1;
13781
+ paintRemoteFleetControlBinaryFrame(controlSession, frame)
13782
+ .catch(error => {
13783
+ window.RuntimeTrace?.emit?.('remote.control.binaryPaintFailed', {
13784
+ nodeId: session.nodeId,
13785
+ deviceId: controlSession.deviceId,
13786
+ error: error?.message || String(error || '')
13787
+ });
13788
+ });
13789
+ });
13790
+ }
13791
+
13792
+ const controlUsesPayloadBlob = controlPaintQueued > 0
13793
+ && !!frame._remoteFleetPayloadBlob
13794
+ && typeof createImageBitmap === 'function';
13795
+ if (applied <= 0
13796
+ && (controlPaintQueued <= 0 || controlUsesPayloadBlob)
13797
+ && frame._remoteFleetObjectUrl
13798
+ && typeof URL !== 'undefined'
13799
+ && typeof URL.revokeObjectURL === 'function') {
13751
13800
  URL.revokeObjectURL(frame._remoteFleetObjectUrl);
13752
13801
  }
13753
13802
  })
@@ -13798,6 +13847,7 @@
13798
13847
  reconnectTimer: null,
13799
13848
  subscriptionTimer: null,
13800
13849
  subscriptionKey: '',
13850
+ controlSessions: new Set(),
13801
13851
  getDeviceIds: null
13802
13852
  };
13803
13853
  remoteFleetBinaryFrameSessions.set(nodeId, session);
@@ -13818,7 +13868,8 @@
13818
13868
 
13819
13869
  delete bodyView._remoteFleetBinaryFrameSession;
13820
13870
  session.bodies.delete(bodyView);
13821
- if (session.bodies.size > 0) {
13871
+ if (session.bodies.size > 0 || (session.controlSessions instanceof Set && session.controlSessions.size > 0)) {
13872
+ refreshRemoteFleetBinaryFrameSubscription(session, true);
13822
13873
  return;
13823
13874
  }
13824
13875
 
@@ -14852,6 +14903,7 @@
14852
14903
 
14853
14904
  activeRemoteFleetControlPopup = null;
14854
14905
  session.active = false;
14906
+ detachRemoteFleetControlBinaryFrameSession(session);
14855
14907
  if (session.timer) {
14856
14908
  clearTimeout(session.timer);
14857
14909
  session.timer = null;
@@ -14873,6 +14925,66 @@
14873
14925
  }
14874
14926
  }
14875
14927
 
14928
+ function attachRemoteFleetControlBinaryFrameSession(controlSession, bodyView) {
14929
+ if (!controlSession?.active || !bodyView || typeof WebSocket !== 'function') {
14930
+ return false;
14931
+ }
14932
+
14933
+ let binarySession = bodyView._remoteFleetBinaryFrameSession || null;
14934
+ if (!binarySession) {
14935
+ if (!startRemoteFleetBinaryFrameSocket(bodyView, () => [])) {
14936
+ return false;
14937
+ }
14938
+ binarySession = bodyView._remoteFleetBinaryFrameSession || null;
14939
+ }
14940
+
14941
+ if (!binarySession) {
14942
+ return false;
14943
+ }
14944
+
14945
+ if (!(binarySession.controlSessions instanceof Set)) {
14946
+ binarySession.controlSessions = new Set();
14947
+ }
14948
+
14949
+ binarySession.controlSessions.add(controlSession);
14950
+ controlSession.binaryFrameSession = binarySession;
14951
+ controlSession.binaryFramePreferred = true;
14952
+ refreshRemoteFleetBinaryFrameSubscription(binarySession, true);
14953
+ openRemoteFleetBinaryFrameSocket(binarySession).catch(() => undefined);
14954
+ return true;
14955
+ }
14956
+
14957
+ function detachRemoteFleetControlBinaryFrameSession(controlSession) {
14958
+ const binarySession = controlSession?.binaryFrameSession;
14959
+ if (!binarySession?.controlSessions) {
14960
+ return;
14961
+ }
14962
+
14963
+ binarySession.controlSessions.delete(controlSession);
14964
+ delete controlSession.binaryFrameSession;
14965
+ refreshRemoteFleetBinaryFrameSubscription(binarySession, true);
14966
+
14967
+ if (binarySession.bodies.size === 0 && binarySession.controlSessions.size === 0) {
14968
+ if (binarySession.reconnectTimer) {
14969
+ clearTimeout(binarySession.reconnectTimer);
14970
+ binarySession.reconnectTimer = null;
14971
+ }
14972
+ if (binarySession.subscriptionTimer) {
14973
+ clearInterval(binarySession.subscriptionTimer);
14974
+ binarySession.subscriptionTimer = null;
14975
+ }
14976
+ if (binarySession.ws) {
14977
+ try {
14978
+ binarySession.ws.close();
14979
+ } catch {
14980
+ // Ignore WebSocket close failures.
14981
+ }
14982
+ binarySession.ws = null;
14983
+ }
14984
+ remoteFleetBinaryFrameSessions.delete(binarySession.nodeId);
14985
+ }
14986
+ }
14987
+
14876
14988
  async function paintRemoteFleetControlFrame(session, frame) {
14877
14989
  if (!session?.active || !frame || !isRemoteFleetFrameSource(frame.frameUrl)) {
14878
14990
  return false;
@@ -14904,6 +15016,59 @@
14904
15016
  }
14905
15017
  }
14906
15018
 
15019
+ async function paintRemoteFleetControlBinaryFrame(session, frame) {
15020
+ if (!session?.active || !frame || String(frame.kind || '').toLowerCase() !== 'live') {
15021
+ return false;
15022
+ }
15023
+
15024
+ const frameSeq = Number(frame.frameSeq || frame.FrameSeq || 0) || 0;
15025
+ if (frameSeq > 0 && frameSeq < (session.lastControlFrameSeq || 0)) {
15026
+ return false;
15027
+ }
15028
+
15029
+ if (frameSeq > 0) {
15030
+ session.lastControlFrameSeq = frameSeq;
15031
+ }
15032
+
15033
+ let bitmap = null;
15034
+ try {
15035
+ if (frame._remoteFleetPayloadBlob && typeof createImageBitmap === 'function') {
15036
+ bitmap = await createImageBitmap(frame._remoteFleetPayloadBlob);
15037
+ } else if (isRemoteFleetFrameSource(frame.frameUrl)) {
15038
+ bitmap = await loadRemoteFleetFrameBitmap(frame);
15039
+ }
15040
+
15041
+ if (!bitmap || !session.active) {
15042
+ return false;
15043
+ }
15044
+
15045
+ requestRemoteFleetFrameLoopFrame(() => {
15046
+ if (!session.active
15047
+ || !document.body.contains(session.overlay)
15048
+ || (frameSeq > 0 && frameSeq < (session.lastControlFrameSeq || 0))) {
15049
+ if (typeof bitmap.close === 'function') {
15050
+ bitmap.close();
15051
+ }
15052
+ return;
15053
+ }
15054
+
15055
+ drawRemoteFleetFrameToCanvas(session.canvas, bitmap, 'contain');
15056
+ session.canvas.style.display = 'block';
15057
+ session.lastControlFrameAt = Date.now();
15058
+ session.status.textContent = `Control ${REMOTE_FLEET_CONTROL_LIVE_FPS}fps`;
15059
+ if (typeof bitmap.close === 'function') {
15060
+ bitmap.close();
15061
+ }
15062
+ });
15063
+ return true;
15064
+ } catch {
15065
+ if (bitmap && typeof bitmap.close === 'function') {
15066
+ bitmap.close();
15067
+ }
15068
+ return false;
15069
+ }
15070
+ }
15071
+
14907
15072
  function sendRemoteFleetControlInput(session, payload, throttleMove = false) {
14908
15073
  if (!session?.active || !payload?.type) {
14909
15074
  return;
@@ -15224,16 +15389,29 @@
15224
15389
  timer: null,
15225
15390
  moveTimer: null,
15226
15391
  pendingMove: null,
15227
- lastMoveSentAt: 0
15392
+ lastMoveSentAt: 0,
15393
+ lastControlFrameAt: 0,
15394
+ lastControlFrameSeq: 0,
15395
+ binaryFramePreferred: false
15228
15396
  };
15229
15397
  activeRemoteFleetControlPopup = session;
15230
15398
  bindRemoteFleetControlInput(session);
15399
+ attachRemoteFleetControlBinaryFrameSession(session, bodyView);
15231
15400
 
15232
15401
  const refresh = async () => {
15233
15402
  if (!session.active) {
15234
15403
  return;
15235
15404
  }
15236
15405
 
15406
+ const now = Date.now();
15407
+ const hasFreshBinaryFrame = session.binaryFramePreferred === true
15408
+ && session.lastControlFrameAt > 0
15409
+ && now - session.lastControlFrameAt < 1200;
15410
+ if (hasFreshBinaryFrame) {
15411
+ session.timer = setTimeout(refresh, 500);
15412
+ return;
15413
+ }
15414
+
15237
15415
  try {
15238
15416
  const result = await invokeDotNetAsync('GetRemoteFleetFrameFromJs', nodeId, targetId, 'live');
15239
15417
  const frame = normalizeRemoteFleetFramePayload(result?.frame || result?.Frame, 'live');
@@ -15241,7 +15419,8 @@
15241
15419
  frame.deviceId = frame.deviceId || targetId;
15242
15420
  await paintRemoteFleetControlFrame(session, frame);
15243
15421
  applyRemoteFleetFramePatches(bodyView, [frame]);
15244
- status.textContent = 'Control';
15422
+ session.lastControlFrameAt = Date.now();
15423
+ status.textContent = session.binaryFramePreferred ? 'Control fallback' : `Control ${REMOTE_FLEET_CONTROL_LIVE_FPS}fps`;
15245
15424
  } else if (result?.error || result?.Error) {
15246
15425
  status.textContent = result.error || result.Error;
15247
15426
  }
@@ -15249,7 +15428,7 @@
15249
15428
  status.textContent = error?.message || 'Frame failed';
15250
15429
  } finally {
15251
15430
  if (session.active) {
15252
- session.timer = setTimeout(refresh, REMOTE_FLEET_LIVE_FRAME_REFRESH_MS);
15431
+ session.timer = setTimeout(refresh, REMOTE_FLEET_CONTROL_FRAME_REFRESH_MS);
15253
15432
  }
15254
15433
  }
15255
15434
  };
@@ -15273,7 +15452,7 @@
15273
15452
  deviceId: targetId
15274
15453
  });
15275
15454
 
15276
- invokeDotNetAsync('StartRemoteFleetLiveStreamFromJs', nodeId, targetId)
15455
+ invokeDotNetAsync('StartRemoteFleetLiveStreamFromJs', nodeId, targetId, REMOTE_FLEET_CONTROL_LIVE_FPS)
15277
15456
  .then(async result => {
15278
15457
  if (!session.active) {
15279
15458
  return;
@@ -15282,7 +15461,7 @@
15282
15461
  await syncRemoteFleetNodeStateFromResult(result);
15283
15462
  session.startedStream = result?.success === true || result?.Success === true;
15284
15463
  session.streamId = String(result?.streamId || result?.StreamId || '');
15285
- status.textContent = session.startedStream ? 'Control' : (result?.error || result?.Error || 'View');
15464
+ status.textContent = session.startedStream ? `Control ${REMOTE_FLEET_CONTROL_LIVE_FPS}fps` : (result?.error || result?.Error || 'View');
15286
15465
  refresh();
15287
15466
  })
15288
15467
  .catch(error => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "mainAssemblyName": "MindExecution.Web",
3
3
  "resources": {
4
- "hash": "sha256-8Fvmr2gwPca8frlDucd8gkb1BGymLVRCbTINI76yI5s=",
4
+ "hash": "sha256-JxTp+hXYDhd47gICFMzpCDWm8b4z1JGet67SEEI1F3c=",
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.pbzp3jfync.dll": "MindExecution.Kernel.dll",
128
128
  "MindExecution.Plugins.Admin.gxzwlji1cf.dll": "MindExecution.Plugins.Admin.dll",
129
129
  "MindExecution.Plugins.Business.vtaey8c59y.dll": "MindExecution.Plugins.Business.dll",
130
- "MindExecution.Plugins.Concept.e1j4pkp0uf.dll": "MindExecution.Plugins.Concept.dll",
130
+ "MindExecution.Plugins.Concept.85y7un1ks6.dll": "MindExecution.Plugins.Concept.dll",
131
131
  "MindExecution.Plugins.Directory.zc8ffaoknd.dll": "MindExecution.Plugins.Directory.dll",
132
- "MindExecution.Plugins.PlanMaster.yfeqppy3kf.dll": "MindExecution.Plugins.PlanMaster.dll",
133
- "MindExecution.Plugins.YouTube.vzjd4jwanl.dll": "MindExecution.Plugins.YouTube.dll",
134
- "MindExecution.Shared.6xjhkrpfwd.dll": "MindExecution.Shared.dll",
135
- "MindExecution.Web.03g8r8265y.dll": "MindExecution.Web.dll",
132
+ "MindExecution.Plugins.PlanMaster.ylooagumgh.dll": "MindExecution.Plugins.PlanMaster.dll",
133
+ "MindExecution.Plugins.YouTube.azfozpumhv.dll": "MindExecution.Plugins.YouTube.dll",
134
+ "MindExecution.Shared.mppf8quyau.dll": "MindExecution.Shared.dll",
135
+ "MindExecution.Web.tln762tijf.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.fc9cjbjplq.dll": "sha256-TymUFwryFLdbCYy2U5qdgE2ZV1yHaLR9bgyrmx6Tcp0=",
282
282
  "MindExecution.Kernel.pbzp3jfync.dll": "sha256-Ff6WHyLD39V0fEjUiQlxX9Y+edssyTH+7T4zfBdj3s0=",
283
- "MindExecution.Plugins.Concept.e1j4pkp0uf.dll": "sha256-nq1Uv/H+JSyGBzGym6AKbVMSa53sktNACog3+JqITI4=",
284
- "MindExecution.Plugins.PlanMaster.yfeqppy3kf.dll": "sha256-YpcXMAmctAWAbfzFrfcYmk3sOo7j8hZGGKsrv4VgqUs=",
285
- "MindExecution.Shared.6xjhkrpfwd.dll": "sha256-5lCRRlgeky/uSmxPrO5acuFLOjfRphWQwSyVY5E1Tq8=",
286
- "MindExecution.Web.03g8r8265y.dll": "sha256-lEHwMVSR1YHsNoejZYt53SRBrYrN/4Ak7dqMqNEnXrg="
283
+ "MindExecution.Plugins.Concept.85y7un1ks6.dll": "sha256-ZK10a6NfAZTCKX0BpiH6e+pBatMwTeXMCtA79A+zGQg=",
284
+ "MindExecution.Plugins.PlanMaster.ylooagumgh.dll": "sha256-aoNSkErjCAqRgET/An00bm2GP3Jsnnu4hz8e/jpaLcI=",
285
+ "MindExecution.Shared.mppf8quyau.dll": "sha256-FsB415v0PlO8/788VKC99rE/BhViR61KcM9+Crxo9Ok=",
286
+ "MindExecution.Web.tln762tijf.dll": "sha256-vy73kyPmRU7hqhUFOFs9fdsn5AWmO7cNTRDoWigkc2M="
287
287
  },
288
288
  "lazyAssembly": {
289
289
  "MindExecution.Plugins.Admin.gxzwlji1cf.dll": "sha256-5D5B2ZuUMj46zBMgH2dRA7CbQf++uukMPrEliFLuZWs=",
290
290
  "MindExecution.Plugins.Business.vtaey8c59y.dll": "sha256-rU9MzRRmHuj0/IluV1dvE6x3aRCK/DA4DWKy1DO4VVg=",
291
291
  "MindExecution.Plugins.Directory.zc8ffaoknd.dll": "sha256-Ey/HajaVuBxB/Ou4qsM70nhAZBoODeCENzG1J/uEsxs=",
292
- "MindExecution.Plugins.YouTube.vzjd4jwanl.dll": "sha256-e9Z1x+BJvcFG38RiQW4jiGg3wFvgH6TBjYIDXPBxOPk="
292
+ "MindExecution.Plugins.YouTube.azfozpumhv.dll": "sha256-GjL5SM7+D8SKJBE528Y5Py29kQrTXPmG5OFr6+E0L4s="
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=20260616-remote-ws-binary-frames-v572" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260616-remote-ws-binary-frames-v572" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260616-remote-ws-control-frames-v573" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260616-remote-ws-control-frames-v573" />
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-remote-ws-binary-frames-v572';
582
+ const scriptVersion = '20260616-remote-ws-control-frames-v573';
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": "DOWuXy9Z",
2
+ "version": "pV7f33KI",
3
3
  "assets": [
4
4
  {
5
5
  "hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
@@ -78,7 +78,7 @@
78
78
  "url": "_content/MindExecution.Shared/js/marked.min.js"
79
79
  },
80
80
  {
81
- "hash": "sha256-HZDEcs9fkSz0iNXD6WOKZwOj8VrjJD+r4oRH9XBQhjA=",
81
+ "hash": "sha256-oDfBxq3aqmSU1z5MGGpE9ZeTdsBtrykHEBnygOVFJtE=",
82
82
  "url": "_content/MindExecution.Shared/js/mind-map-core.js"
83
83
  },
84
84
  {
@@ -86,7 +86,7 @@
86
86
  "url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
87
87
  },
88
88
  {
89
- "hash": "sha256-KgIwiH8bPKxBAXnomKCDPKRgD/hL6CSeV2nM5EpyMdQ=",
89
+ "hash": "sha256-8uQGgnoT3SXKM89hTz49ThSpGgT88GRP7ipe8xlR3z0=",
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.vtaey8c59y.dll"
427
427
  },
428
428
  {
429
- "hash": "sha256-nq1Uv/H+JSyGBzGym6AKbVMSa53sktNACog3+JqITI4=",
430
- "url": "_framework/MindExecution.Plugins.Concept.e1j4pkp0uf.dll"
429
+ "hash": "sha256-ZK10a6NfAZTCKX0BpiH6e+pBatMwTeXMCtA79A+zGQg=",
430
+ "url": "_framework/MindExecution.Plugins.Concept.85y7un1ks6.dll"
431
431
  },
432
432
  {
433
433
  "hash": "sha256-Ey/HajaVuBxB/Ou4qsM70nhAZBoODeCENzG1J/uEsxs=",
434
434
  "url": "_framework/MindExecution.Plugins.Directory.zc8ffaoknd.dll"
435
435
  },
436
436
  {
437
- "hash": "sha256-YpcXMAmctAWAbfzFrfcYmk3sOo7j8hZGGKsrv4VgqUs=",
438
- "url": "_framework/MindExecution.Plugins.PlanMaster.yfeqppy3kf.dll"
437
+ "hash": "sha256-aoNSkErjCAqRgET/An00bm2GP3Jsnnu4hz8e/jpaLcI=",
438
+ "url": "_framework/MindExecution.Plugins.PlanMaster.ylooagumgh.dll"
439
439
  },
440
440
  {
441
- "hash": "sha256-e9Z1x+BJvcFG38RiQW4jiGg3wFvgH6TBjYIDXPBxOPk=",
442
- "url": "_framework/MindExecution.Plugins.YouTube.vzjd4jwanl.dll"
441
+ "hash": "sha256-GjL5SM7+D8SKJBE528Y5Py29kQrTXPmG5OFr6+E0L4s=",
442
+ "url": "_framework/MindExecution.Plugins.YouTube.azfozpumhv.dll"
443
443
  },
444
444
  {
445
- "hash": "sha256-5lCRRlgeky/uSmxPrO5acuFLOjfRphWQwSyVY5E1Tq8=",
446
- "url": "_framework/MindExecution.Shared.6xjhkrpfwd.dll"
445
+ "hash": "sha256-FsB415v0PlO8/788VKC99rE/BhViR61KcM9+Crxo9Ok=",
446
+ "url": "_framework/MindExecution.Shared.mppf8quyau.dll"
447
447
  },
448
448
  {
449
- "hash": "sha256-lEHwMVSR1YHsNoejZYt53SRBrYrN/4Ak7dqMqNEnXrg=",
450
- "url": "_framework/MindExecution.Web.03g8r8265y.dll"
449
+ "hash": "sha256-vy73kyPmRU7hqhUFOFs9fdsn5AWmO7cNTRDoWigkc2M=",
450
+ "url": "_framework/MindExecution.Web.tln762tijf.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-pATnlidoWPOV2BpRonMlb3bDjtALaA8sXI+DiPFY4/0=",
773
+ "hash": "sha256-HDeRZ1juous1GiTsZw+QLukbDxOOYjh72G4Dta2w5Fc=",
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-ANyJXyCBiGthYmrg5ygLEqNR6Vuu+eXOi+fQ/da00pM=",
837
+ "hash": "sha256-VJOyHChPIe+gqQk3r5g4qTjsKYTrLXoP6I5L+o4ZYzE=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: DOWuXy9Z */
1
+ /* Manifest version: pV7f33KI */
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