@mindexec/cli 0.2.157 → 0.2.158

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.157",
3
+ "version": "0.2.158",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -585,15 +585,15 @@ function encodeRemoteBinaryFrame(metadata, payload = new Uint8Array([0xff, 0xd8,
585
585
  return buffer;
586
586
  }
587
587
 
588
- function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTaskBatches = [], lastError = '') {
588
+ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTaskBatches = [], lastError = '', nodeId = 'remote-fleet-render-smoke') {
589
589
  const connected = devices.filter(device => device.Connected).length;
590
590
  const endpoint = hubStatus.agentEndpoint || '127.0.0.1:5197';
591
591
  const pairToken = hubStatus.pairToken || 'render-smoke-token';
592
592
  const hostTargetState = hubStatus.hostTargetActive
593
- ? (hubStatus.hostTargetNodeId === 'remote-fleet-render-smoke' ? 'hosting' : 'other-monitor')
593
+ ? (hubStatus.hostTargetNodeId === nodeId ? 'hosting' : 'other-monitor')
594
594
  : 'inactive';
595
595
  return {
596
- id: 'remote-fleet-render-smoke',
596
+ id: nodeId,
597
597
  contentType: 'templateLauncher',
598
598
  metadata: {
599
599
  SemanticType: 'RemoteFleetMonitor',
@@ -625,10 +625,10 @@ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTask
625
625
  };
626
626
  }
627
627
 
628
- function createRemoteFleetTemplateShell(document, focusDeviceId = '') {
628
+ function createRemoteFleetTemplateShell(document, focusDeviceId = '', nodeId = 'remote-fleet-render-smoke') {
629
629
  const nodeShell = document.createElement('div');
630
630
  nodeShell.setAttribute('class', 'map-node-template-card map-node-remote-fleet');
631
- nodeShell.dataset.nodeId = 'remote-fleet-render-smoke';
631
+ nodeShell.dataset.nodeId = nodeId;
632
632
  const shell = document.createElement('div');
633
633
  shell.setAttribute('class', 'template-card__shell template-card__shell--remote-fleet');
634
634
  const header = document.createElement('div');
@@ -642,7 +642,7 @@ function createRemoteFleetTemplateShell(document, focusDeviceId = '') {
642
642
  header.appendChild(titleWrap);
643
643
  const bodyView = document.createElement('div');
644
644
  bodyView.setAttribute('class', 'template-card__remote-fleet-body map-node-remote-fleet__body');
645
- bodyView.dataset.nodeId = 'remote-fleet-render-smoke';
645
+ bodyView.dataset.nodeId = nodeId;
646
646
  bodyView.dataset.remoteFleetAutoMonitor = 'false';
647
647
  if (focusDeviceId) {
648
648
  bodyView.dataset.remoteFleetFocusDeviceId = focusDeviceId;
@@ -1107,6 +1107,36 @@ try {
1107
1107
  assert.equal(rerenderedPatchPreview.dataset.remoteFleetFrameSeq, String(websocketFrameSeq));
1108
1108
  assert.equal(rerenderedPatchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]')?.style.display, 'block');
1109
1109
 
1110
+ const otherBoardNodeId = 'remote-fleet-render-smoke-other-board';
1111
+ const { nodeShell: otherBoardShell, bodyView: otherBoardBodyView } =
1112
+ createRemoteFleetTemplateShell(document, focusedDevice.DeviceId, otherBoardNodeId);
1113
+ document.body.appendChild(otherBoardShell);
1114
+ manager.renderRemoteFleetMonitorForTest(
1115
+ otherBoardBodyView,
1116
+ buildMonitorNode(
1117
+ devices,
1118
+ hub.getStatus({ includeSecrets: true }),
1119
+ latestTaskBatch,
1120
+ recentTaskBatches,
1121
+ '',
1122
+ otherBoardNodeId));
1123
+ await wait(30);
1124
+ const otherBoardPatchPreview = otherBoardBodyView
1125
+ .querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`)
1126
+ ?.querySelector('[data-remote-fleet-device-preview="tile"]');
1127
+ assert.ok(otherBoardPatchPreview);
1128
+ assert.equal(
1129
+ otherBoardPatchPreview.dataset.remoteFleetFrameSeq,
1130
+ String(websocketFrameSeq),
1131
+ 'a different-board MDM should prime from the device-global latest binary frame cache');
1132
+ assert.equal(
1133
+ otherBoardPatchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]')?.style.display,
1134
+ 'block');
1135
+ assert.ok(diagnostics.runtimeTrace.some(event =>
1136
+ event.type === 'remote.frame.wsCachePrimed'
1137
+ && event.nodeId === otherBoardNodeId));
1138
+ otherBoardShell.remove();
1139
+
1110
1140
  const controlCard = bodyView.querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`);
1111
1141
  assert.ok(controlCard);
1112
1142
  controlCard.dispatchEvent({ type: 'dblclick', button: 0 });
@@ -13511,6 +13511,7 @@
13511
13511
  const REMOTE_FLEET_BINARY_FRAME_CONNECT_GRACE_MS = 1600;
13512
13512
  const REMOTE_FLEET_BINARY_FRAME_CACHE_MS = 10000;
13513
13513
  const REMOTE_FLEET_BINARY_FRAME_CACHE_LIMIT = 240;
13514
+ const REMOTE_FLEET_BINARY_FRAME_SESSION_IDLE_MS = 8000;
13514
13515
  const REMOTE_FLEET_AUTO_LIVE_START_MAX_PARALLEL = 8;
13515
13516
  const REMOTE_FLEET_AUTO_LIVE_START_COOLDOWN_MS = 3000;
13516
13517
  const REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS = 250;
@@ -13522,6 +13523,7 @@
13522
13523
  const remoteFleetHostLeaseTimers = new Map();
13523
13524
  const remoteFleetLocalHostTargets = new Map();
13524
13525
  const remoteFleetBinaryFrameSessions = new Map();
13526
+ const remoteFleetLatestBinaryFrames = new Map();
13525
13527
  const remoteFleetFrameBlobCache = new Map();
13526
13528
  let remoteFleetBridgeStatusPromise = null;
13527
13529
  let activeRemoteFleetControlPopup = null;
@@ -13948,36 +13950,85 @@
13948
13950
  }
13949
13951
  }
13950
13952
 
13953
+ function pruneRemoteFleetGlobalBinaryFrameCache() {
13954
+ const now = getRemoteFleetFrameNow();
13955
+ for (const [deviceId, entry] of remoteFleetLatestBinaryFrames) {
13956
+ if (!deviceId
13957
+ || !entry
13958
+ || !entry.frame
13959
+ || now - Number(entry.seenAt || 0) > REMOTE_FLEET_BINARY_FRAME_CACHE_MS
13960
+ || remoteFleetLatestBinaryFrames.size > REMOTE_FLEET_BINARY_FRAME_CACHE_LIMIT) {
13961
+ remoteFleetLatestBinaryFrames.delete(deviceId);
13962
+ }
13963
+ }
13964
+ }
13965
+
13951
13966
  function rememberRemoteFleetBinaryFrame(session, frame) {
13952
13967
  const deviceId = String(frame?.deviceId || '').trim();
13953
- if (!session || !deviceId || !frame?._remoteFleetPayloadBlob) {
13968
+ if (!deviceId || !frame?._remoteFleetPayloadBlob) {
13954
13969
  return;
13955
13970
  }
13956
13971
 
13957
- if (!(session.latestBinaryFrames instanceof Map)) {
13958
- session.latestBinaryFrames = new Map();
13959
- }
13960
-
13961
- pruneRemoteFleetBinaryFrameCache(session);
13962
- session.latestBinaryFrames.set(deviceId, {
13972
+ const entry = {
13963
13973
  seenAt: getRemoteFleetFrameNow(),
13964
13974
  frame: cloneRemoteFleetFramePatch(frame)
13965
- });
13975
+ };
13976
+
13977
+ if (session) {
13978
+ if (!(session.latestBinaryFrames instanceof Map)) {
13979
+ session.latestBinaryFrames = new Map();
13980
+ }
13981
+
13982
+ pruneRemoteFleetBinaryFrameCache(session);
13983
+ session.latestBinaryFrames.set(deviceId, {
13984
+ seenAt: entry.seenAt,
13985
+ frame: cloneRemoteFleetFramePatch(frame)
13986
+ });
13987
+ }
13988
+
13989
+ pruneRemoteFleetGlobalBinaryFrameCache();
13990
+ remoteFleetLatestBinaryFrames.set(deviceId, entry);
13966
13991
  }
13967
13992
 
13968
13993
  function applyRemoteFleetBinaryFrameCacheToBody(bodyView, session) {
13969
- if (!bodyView || !(session?.latestBinaryFrames instanceof Map) || session.latestBinaryFrames.size === 0) {
13994
+ if (!bodyView) {
13970
13995
  return 0;
13971
13996
  }
13972
13997
 
13973
- pruneRemoteFleetBinaryFrameCache(session);
13974
- const patches = [];
13975
- for (const entry of session.latestBinaryFrames.values()) {
13976
- if (entry?.frame) {
13977
- patches.push(cloneRemoteFleetFramePatch(entry.frame));
13998
+ const patchesByDeviceId = new Map();
13999
+ const allowedDeviceIds = new Set(getRemoteFleetBinaryFrameDeviceIds(session));
14000
+ const addFrame = entry => {
14001
+ const frame = entry?.frame;
14002
+ const deviceId = String(frame?.deviceId || '').trim();
14003
+ if (!deviceId || !frame) {
14004
+ return;
13978
14005
  }
14006
+
14007
+ if (allowedDeviceIds.size > 0 && !allowedDeviceIds.has(deviceId)) {
14008
+ return;
14009
+ }
14010
+
14011
+ const existing = patchesByDeviceId.get(deviceId);
14012
+ const existingSeq = Number(existing?.frameSeq || 0);
14013
+ const nextSeq = Number(frame.frameSeq || 0);
14014
+ if (!existing || nextSeq >= existingSeq) {
14015
+ patchesByDeviceId.set(deviceId, cloneRemoteFleetFramePatch(frame));
14016
+ }
14017
+ };
14018
+
14019
+ if (session?.latestBinaryFrames instanceof Map && session.latestBinaryFrames.size > 0) {
14020
+ pruneRemoteFleetBinaryFrameCache(session);
14021
+ for (const entry of session.latestBinaryFrames.values()) {
14022
+ addFrame(entry);
14023
+ }
14024
+ }
14025
+
14026
+ pruneRemoteFleetGlobalBinaryFrameCache();
14027
+ for (const entry of remoteFleetLatestBinaryFrames.values()) {
14028
+ addFrame(entry);
13979
14029
  }
13980
14030
 
14031
+ const patches = Array.from(patchesByDeviceId.values());
13981
14032
  return patches.length > 0
13982
14033
  ? applyRemoteFleetFramePatches(bodyView, patches)
13983
14034
  : 0;
@@ -14256,6 +14307,69 @@
14256
14307
  }, REMOTE_FLEET_BINARY_FRAME_WS_RECONNECT_MS);
14257
14308
  }
14258
14309
 
14310
+ function cancelRemoteFleetBinaryFrameSessionRelease(session) {
14311
+ if (!session?.releaseTimer) {
14312
+ return;
14313
+ }
14314
+
14315
+ clearTimeout(session.releaseTimer);
14316
+ session.releaseTimer = null;
14317
+ }
14318
+
14319
+ function closeRemoteFleetBinaryFrameSession(session, reason = 'close') {
14320
+ if (!session) {
14321
+ return;
14322
+ }
14323
+
14324
+ cancelRemoteFleetBinaryFrameSessionRelease(session);
14325
+ if (session.reconnectTimer) {
14326
+ clearTimeout(session.reconnectTimer);
14327
+ session.reconnectTimer = null;
14328
+ }
14329
+ if (session.subscriptionTimer) {
14330
+ clearInterval(session.subscriptionTimer);
14331
+ session.subscriptionTimer = null;
14332
+ }
14333
+ if (session.ws) {
14334
+ try {
14335
+ session.ws.close();
14336
+ } catch {
14337
+ // Ignore WebSocket close failures.
14338
+ }
14339
+ session.ws = null;
14340
+ }
14341
+ remoteFleetBinaryFrameSessions.delete(session.nodeId);
14342
+ window.RuntimeTrace?.emit?.('remote.frame.wsSessionClosed', {
14343
+ nodeId: session.nodeId,
14344
+ reason
14345
+ });
14346
+ }
14347
+
14348
+ function scheduleRemoteFleetBinaryFrameSessionRelease(session, reason = 'idle') {
14349
+ if (!session
14350
+ || session.releaseTimer
14351
+ || session.bodies.size > 0
14352
+ || (session.controlSessions instanceof Set && session.controlSessions.size > 0)) {
14353
+ return;
14354
+ }
14355
+
14356
+ session.releaseTimer = setTimeout(() => {
14357
+ session.releaseTimer = null;
14358
+ if (session.bodies.size > 0
14359
+ || (session.controlSessions instanceof Set && session.controlSessions.size > 0)) {
14360
+ return;
14361
+ }
14362
+
14363
+ closeRemoteFleetBinaryFrameSession(session, reason);
14364
+ }, REMOTE_FLEET_BINARY_FRAME_SESSION_IDLE_MS);
14365
+ session.releaseTimer?.unref?.();
14366
+ window.RuntimeTrace?.emit?.('remote.frame.wsSessionIdle', {
14367
+ nodeId: session.nodeId,
14368
+ reason,
14369
+ ttlMs: REMOTE_FLEET_BINARY_FRAME_SESSION_IDLE_MS
14370
+ });
14371
+ }
14372
+
14259
14373
  async function openRemoteFleetBinaryFrameSocket(session) {
14260
14374
  if (!session || (session.bodies.size === 0 && (!session.controlSessions || session.controlSessions.size === 0)) || typeof WebSocket !== 'function') {
14261
14375
  return false;
@@ -14305,7 +14419,17 @@
14305
14419
 
14306
14420
  parseRemoteFleetBinaryFrameMessage(event.data)
14307
14421
  .then(frame => {
14308
- if (!frame || (session.bodies.size === 0 && (!session.controlSessions || session.controlSessions.size === 0))) {
14422
+ if (!frame) {
14423
+ return;
14424
+ }
14425
+
14426
+ const hasFrameConsumers =
14427
+ session.bodies.size > 0
14428
+ || (session.controlSessions instanceof Set && session.controlSessions.size > 0);
14429
+ if (!hasFrameConsumers) {
14430
+ const frameAt = getRemoteFleetFrameNow();
14431
+ session.lastBinaryFrameAt = frameAt;
14432
+ rememberRemoteFleetBinaryFrame(session, frame);
14309
14433
  if (frame?._remoteFleetObjectUrl && typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {
14310
14434
  URL.revokeObjectURL(frame._remoteFleetObjectUrl);
14311
14435
  }
@@ -14408,6 +14532,7 @@
14408
14532
  bodies: new Set(),
14409
14533
  ws: null,
14410
14534
  reconnectTimer: null,
14535
+ releaseTimer: null,
14411
14536
  subscriptionTimer: null,
14412
14537
  subscriptionKey: '',
14413
14538
  latestBinaryFrames: new Map(),
@@ -14417,6 +14542,7 @@
14417
14542
  remoteFleetBinaryFrameSessions.set(nodeId, session);
14418
14543
  }
14419
14544
 
14545
+ cancelRemoteFleetBinaryFrameSessionRelease(session);
14420
14546
  session.bodies.add(bodyView);
14421
14547
  session.getDeviceIds = getDeviceIds;
14422
14548
  session.liveOptions = {
@@ -14428,7 +14554,14 @@
14428
14554
  mode: String(options.mode || 'remote-fast')
14429
14555
  };
14430
14556
  bodyView._remoteFleetBinaryFrameSession = session;
14431
- applyRemoteFleetBinaryFrameCacheToBody(bodyView, session);
14557
+ const primedFrames = applyRemoteFleetBinaryFrameCacheToBody(bodyView, session);
14558
+ if (primedFrames > 0) {
14559
+ bodyView._remoteFleetLastBinaryFrameAt = getRemoteFleetFrameNow();
14560
+ window.RuntimeTrace?.emit?.('remote.frame.wsCachePrimed', {
14561
+ nodeId,
14562
+ count: primedFrames
14563
+ });
14564
+ }
14432
14565
  openRemoteFleetBinaryFrameSocket(session).catch(() => undefined);
14433
14566
  return true;
14434
14567
  }
@@ -14446,23 +14579,7 @@
14446
14579
  return;
14447
14580
  }
14448
14581
 
14449
- if (session.reconnectTimer) {
14450
- clearTimeout(session.reconnectTimer);
14451
- session.reconnectTimer = null;
14452
- }
14453
- if (session.subscriptionTimer) {
14454
- clearInterval(session.subscriptionTimer);
14455
- session.subscriptionTimer = null;
14456
- }
14457
- if (session.ws) {
14458
- try {
14459
- session.ws.close();
14460
- } catch {
14461
- // Ignore WebSocket close failures.
14462
- }
14463
- session.ws = null;
14464
- }
14465
- remoteFleetBinaryFrameSessions.delete(session.nodeId);
14582
+ scheduleRemoteFleetBinaryFrameSessionRelease(session, 'body-detached');
14466
14583
  }
14467
14584
 
14468
14585
  function requestRemoteFleetFrameLoopFrame(callback) {
@@ -15829,23 +15946,7 @@
15829
15946
  refreshRemoteFleetBinaryFrameSubscription(binarySession, true);
15830
15947
 
15831
15948
  if (binarySession.bodies.size === 0 && binarySession.controlSessions.size === 0) {
15832
- if (binarySession.reconnectTimer) {
15833
- clearTimeout(binarySession.reconnectTimer);
15834
- binarySession.reconnectTimer = null;
15835
- }
15836
- if (binarySession.subscriptionTimer) {
15837
- clearInterval(binarySession.subscriptionTimer);
15838
- binarySession.subscriptionTimer = null;
15839
- }
15840
- if (binarySession.ws) {
15841
- try {
15842
- binarySession.ws.close();
15843
- } catch {
15844
- // Ignore WebSocket close failures.
15845
- }
15846
- binarySession.ws = null;
15847
- }
15848
- remoteFleetBinaryFrameSessions.delete(binarySession.nodeId);
15949
+ scheduleRemoteFleetBinaryFrameSessionRelease(binarySession, 'control-detached');
15849
15950
  }
15850
15951
  }
15851
15952
 
@@ -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=20260617-auth-mirror-v590" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-auth-mirror-v590" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260617-mdm-tab-fast-v591" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-mdm-tab-fast-v591" />
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 = '20260617-auth-mirror-v590';
582
+ const scriptVersion = '20260617-mdm-tab-fast-v591';
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": "GgmfxCXF",
2
+ "version": "2guH6APA",
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-1ImfUjyr1aBodcgICy6KTDGinJHMb1jdRG2MYGPdYvE=",
89
+ "hash": "sha256-piKsRYcnSTaqs+vd7QATTt7cGBN5hHPbY6P8Xjl2J6k=",
90
90
  "url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
91
91
  },
92
92
  {
@@ -834,7 +834,7 @@
834
834
  "url": "image-manifest.json"
835
835
  },
836
836
  {
837
- "hash": "sha256-RLe/OcetCLrQfgXCZMRe1KAmWd4NRvzz9LOOJ0dr7p0=",
837
+ "hash": "sha256-hq0qYVhXCK09hkKo9EkKj84gbxqFCuf2l4XAWk1gfL0=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: GgmfxCXF */
1
+ /* Manifest version: 2guH6APA */
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