@mindexec/cli 0.2.138 → 0.2.140

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.138",
3
+ "version": "0.2.140",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -419,6 +419,10 @@ async function loadCss3DManager() {
419
419
  const objectUrlCalls = [];
420
420
  const revokedObjectUrls = [];
421
421
  const imageBitmapCalls = [];
422
+ const fetchCalls = [];
423
+ const runtimeTrace = [];
424
+ const webSocketConnections = [];
425
+ const webSocketSends = [];
422
426
  class SmokeURL extends URL {}
423
427
  SmokeURL.createObjectURL = blob => {
424
428
  objectUrlCalls.push(blob);
@@ -427,9 +431,43 @@ async function loadCss3DManager() {
427
431
  SmokeURL.revokeObjectURL = value => {
428
432
  revokedObjectUrls.push(String(value || ''));
429
433
  };
434
+ class MiniWebSocket {
435
+ static CONNECTING = 0;
436
+ static OPEN = 1;
437
+ static CLOSING = 2;
438
+ static CLOSED = 3;
439
+
440
+ constructor(url) {
441
+ this.url = String(url || '');
442
+ this.readyState = MiniWebSocket.CONNECTING;
443
+ this.binaryType = '';
444
+ this.sent = [];
445
+ webSocketConnections.push(this);
446
+ setTimeout(() => {
447
+ if (this.readyState !== MiniWebSocket.CONNECTING) return;
448
+ this.readyState = MiniWebSocket.OPEN;
449
+ this.onopen?.({ type: 'open' });
450
+ }, 0);
451
+ }
452
+
453
+ send(payload) {
454
+ const text = typeof payload === 'string' ? payload : String(payload || '');
455
+ this.sent.push(text);
456
+ webSocketSends.push({ url: this.url, payload: text });
457
+ }
458
+
459
+ close() {
460
+ if (this.readyState === MiniWebSocket.CLOSED) return;
461
+ this.readyState = MiniWebSocket.CLOSED;
462
+ this.onclose?.({ type: 'close' });
463
+ }
464
+ }
430
465
  const context = {
431
466
  console,
432
467
  document,
468
+ location: {
469
+ origin: 'http://localhost:5147'
470
+ },
433
471
  navigator: {
434
472
  clipboard: {
435
473
  writeText: async () => {}
@@ -466,6 +504,23 @@ async function loadCss3DManager() {
466
504
  },
467
505
  THREE: createThreeStub(),
468
506
  URL: SmokeURL,
507
+ WebSocket: MiniWebSocket,
508
+ fetch: async (url, options = {}) => {
509
+ fetchCalls.push({ url: String(url || ''), options });
510
+ return {
511
+ ok: true,
512
+ status: 200,
513
+ json: async () => ({
514
+ bridgeToken: 'render-smoke-bridge-token',
515
+ remoteFrameWsPath: '/api/remote/frames/ws'
516
+ })
517
+ };
518
+ },
519
+ RuntimeTrace: {
520
+ emit(type, data = {}) {
521
+ runtimeTrace.push({ type, ...data });
522
+ }
523
+ },
469
524
  Promise
470
525
  };
471
526
  context.window = context;
@@ -478,7 +533,11 @@ async function loadCss3DManager() {
478
533
  diagnostics: {
479
534
  objectUrlCalls,
480
535
  revokedObjectUrls,
481
- imageBitmapCalls
536
+ imageBitmapCalls,
537
+ fetchCalls,
538
+ runtimeTrace,
539
+ webSocketConnections,
540
+ webSocketSends
482
541
  }
483
542
  };
484
543
  }
@@ -530,6 +589,7 @@ function buildMonitorNode(devices, hubStatus, latestTaskBatch = null, recentTask
530
589
  function createRemoteFleetTemplateShell(document, focusDeviceId = '') {
531
590
  const nodeShell = document.createElement('div');
532
591
  nodeShell.setAttribute('class', 'map-node-template-card map-node-remote-fleet');
592
+ nodeShell.dataset.nodeId = 'remote-fleet-render-smoke';
533
593
  const shell = document.createElement('div');
534
594
  shell.setAttribute('class', 'template-card__shell template-card__shell--remote-fleet');
535
595
  const header = document.createElement('div');
@@ -542,7 +602,8 @@ function createRemoteFleetTemplateShell(document, focusDeviceId = '') {
542
602
  header.appendChild(icon);
543
603
  header.appendChild(titleWrap);
544
604
  const bodyView = document.createElement('div');
545
- bodyView.setAttribute('class', 'template-card__remote-fleet-body');
605
+ bodyView.setAttribute('class', 'template-card__remote-fleet-body map-node-remote-fleet__body');
606
+ bodyView.dataset.nodeId = 'remote-fleet-render-smoke';
546
607
  bodyView.dataset.remoteFleetAutoMonitor = 'false';
547
608
  if (focusDeviceId) {
548
609
  bodyView.dataset.remoteFleetFocusDeviceId = focusDeviceId;
@@ -866,9 +927,14 @@ try {
866
927
  assert.equal(binaryImage?.style.display, 'none');
867
928
  assert.equal(diagnostics.imageBitmapCalls.length, imageBitmapCountBeforeBinary + 1);
868
929
  assert.equal(diagnostics.objectUrlCalls.length, objectUrlCountBeforeBinary);
930
+ const binaryDrawCalls = document.canvasDrawCalls.slice(drawCountBeforeBinary);
869
931
  assert.ok(
870
- document.canvasDrawCalls.slice(drawCountBeforeBinary).some(call => call.op === 'drawImage'),
932
+ binaryDrawCalls.some(call => call.op === 'drawImage'),
871
933
  'expected binary Blob frame to draw directly to canvas');
934
+ assert.equal(
935
+ binaryDrawCalls.some(call => call.op === 'clearRect' || call.op === 'fillRect'),
936
+ false,
937
+ 'binary Blob frame paint must not clear/fill the canvas before drawing');
872
938
  const alternateDevice = devices.find(device =>
873
939
  device.Connected === true
874
940
  && device.DeviceId !== focusedDevice.DeviceId);
@@ -934,9 +1000,31 @@ try {
934
1000
  const resultPanel = bodyView.querySelector('[data-remote-fleet-task-results="true"]');
935
1001
  assert.equal(resultPanel, null);
936
1002
  assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
937
- await wait();
1003
+ await wait(20);
938
1004
  const liveStartCalls = dotNetCalls.filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs');
939
- assert.ok(liveStartCalls.length > 1, `expected multiple visible live starts, got ${liveStartCalls.length}`);
1005
+ const subscribeMessages = diagnostics.webSocketSends
1006
+ .map(send => {
1007
+ try {
1008
+ return JSON.parse(send.payload);
1009
+ } catch {
1010
+ return null;
1011
+ }
1012
+ })
1013
+ .filter(Boolean);
1014
+ const autoLiveSubscribe = subscribeMessages.find(message =>
1015
+ message.type === 'subscribe'
1016
+ && message.nodeId === 'remote-fleet-render-smoke'
1017
+ && message.autoStartLive === true);
1018
+ assert.ok(diagnostics.fetchCalls.some(call => call.url.includes('/api/status?remoteFrames=ws')));
1019
+ assert.ok(diagnostics.webSocketConnections.length >= 1, 'expected MDM render to open binary frame WebSocket');
1020
+ assert.ok(autoLiveSubscribe, 'expected MDM render to subscribe with autoStartLive over WebSocket');
1021
+ assert.equal(autoLiveSubscribe.fps, 12);
1022
+ assert.equal(autoLiveSubscribe.maxWidth, 960);
1023
+ assert.equal(autoLiveSubscribe.maxHeight, 540);
1024
+ assert.equal(autoLiveSubscribe.quality, 60);
1025
+ assert.ok(autoLiveSubscribe.deviceIds.length > 1, 'expected visible connected devices in WS subscription');
1026
+ assert.ok(diagnostics.runtimeTrace.some(event => event.type === 'remote.live.wsAutoStartRequested'));
1027
+ assert.equal(liveStartCalls.length, 0, 'WebSocket live path must not call DotNet live-start fallback');
940
1028
  await wait(320);
941
1029
  assert.ok(dotNetCalls.some(call => call.methodName === 'RefreshRemoteFleetMonitorNodeFromJs'));
942
1030
  assert.equal(bodyView.dataset.remoteFleetTaskFollowKey, 'render-smoke-batch');
@@ -13461,7 +13461,7 @@
13461
13461
  const REMOTE_FLEET_FRAME_BLOB_CACHE_LIMIT = 96;
13462
13462
  const REMOTE_FLEET_LIVE_FRAME_DECODE_TIMEOUT_MS = 180;
13463
13463
  const REMOTE_FLEET_THUMBNAIL_FRAME_DECODE_TIMEOUT_MS = 1200;
13464
- const REMOTE_FLEET_BINARY_FRAME_MAX_DECODE_IN_FLIGHT = 2;
13464
+ const REMOTE_FLEET_BINARY_FRAME_MAX_DECODE_IN_FLIGHT = 1;
13465
13465
  const REMOTE_FLEET_BINARY_FRAME_WS_RECONNECT_MS = 1500;
13466
13466
  const REMOTE_FLEET_BINARY_FRAME_SUBSCRIBE_MS = 1000;
13467
13467
  const REMOTE_FLEET_BINARY_FRAME_STALE_FALLBACK_MS = 1400;
@@ -14269,7 +14269,7 @@
14269
14269
  width: 100%;
14270
14270
  height: 100%;
14271
14271
  display: none;
14272
- background: #0f172a;
14272
+ background: transparent;
14273
14273
  `;
14274
14274
  if (typeof preview?.insertBefore === 'function') {
14275
14275
  preview.insertBefore(canvas, preview.firstChild || null);
@@ -14361,9 +14361,6 @@
14361
14361
 
14362
14362
  context.imageSmoothingEnabled = true;
14363
14363
  context.imageSmoothingQuality = 'medium';
14364
- context.fillStyle = '#020617';
14365
- context.clearRect(0, 0, size.width, size.height);
14366
- context.fillRect(0, 0, size.width, size.height);
14367
14364
  context.drawImage(bitmap, sx, sy, sw, sh, dx, dy, dw, dh);
14368
14365
  canvas._remoteFleetContentRect = {
14369
14366
  left: dx / size.dpr,
@@ -18000,12 +17997,6 @@
18000
17997
  const hasVisibleLiveTarget = getVisibleLiveFrameDeviceIds().length > 0
18001
17998
  || devices.some(device => isRemoteFleetDeviceConnected(device) && isRemoteFleetLiveCapable(device));
18002
17999
  if (hasVisibleLiveTarget || hasActiveLiveStream) {
18003
- ensureVisibleRemoteFleetLiveStreams().catch(error => {
18004
- window.RuntimeTrace?.emit?.('remote.live.autoStartFailed', {
18005
- nodeId,
18006
- error: error?.message || String(error || '')
18007
- });
18008
- });
18009
18000
  const binaryFrameSocketStarted = startRemoteFleetBinaryFrameSocket(bodyView, () => {
18010
18001
  const liveIds = getVisibleLiveFrameDeviceIds();
18011
18002
  return liveIds.length > 0 ? liveIds : getVisibleFrameDeviceIds();
@@ -18022,6 +18013,18 @@
18022
18013
  nodeId,
18023
18014
  reason: 'binary-frame-socket-not-started'
18024
18015
  });
18016
+ ensureVisibleRemoteFleetLiveStreams().catch(error => {
18017
+ window.RuntimeTrace?.emit?.('remote.live.autoStartFailed', {
18018
+ nodeId,
18019
+ error: error?.message || String(error || '')
18020
+ });
18021
+ });
18022
+ } else {
18023
+ window.RuntimeTrace?.emit?.('remote.live.wsAutoStartRequested', {
18024
+ nodeId,
18025
+ transport: 'ws-binary',
18026
+ fps: REMOTE_FLEET_MONITOR_LIVE_FPS
18027
+ });
18025
18028
  }
18026
18029
  bodyView._remoteFleetLiveRefreshTimer = setInterval(async () => {
18027
18030
  if (!document.body.contains(bodyView)) {
@@ -1,5 +1,5 @@
1
1
  self.assetsManifest = {
2
- "version": "IfRQGIi2",
2
+ "version": "7WvF4J3m",
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-WBIjGLmIxv1h8qPdh1KvY1XXHi1slyoTo2BVqXis+hQ=",
89
+ "hash": "sha256-8Ndn0qAzhmRH7/OJtB0ve5LG2oN5e+PaAE7c0MyEzHM=",
90
90
  "url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
91
91
  },
92
92
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: IfRQGIi2 */
1
+ /* Manifest version: 7WvF4J3m */
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