@mindexec/cli 0.2.144 → 0.2.146

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.144",
3
+ "version": "0.2.146",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -186,6 +186,16 @@ class MiniElement {
186
186
  return true;
187
187
  }
188
188
 
189
+ focus() {
190
+ this.ownerDocument.activeElement = this;
191
+ }
192
+
193
+ blur() {
194
+ if (this.ownerDocument.activeElement === this) {
195
+ this.ownerDocument.activeElement = null;
196
+ }
197
+ }
198
+
189
199
  getBoundingClientRect() {
190
200
  return {
191
201
  left: 0,
@@ -268,6 +278,7 @@ class MiniDocument {
268
278
  this.body = new MiniElement('body', this);
269
279
  this.head = new MiniElement('head', this);
270
280
  this.canvasDrawCalls = [];
281
+ this.activeElement = null;
271
282
  }
272
283
 
273
284
  createElement(tagName) {
@@ -845,12 +856,41 @@ try {
845
856
  return { success: true };
846
857
  }
847
858
  };
848
- manager.setModuleForTest({ dotNetHelper });
859
+ const moduleRef = {
860
+ dotNetHelper,
861
+ nodeObjectsById: new Map(),
862
+ _visibleIds: new Set(['remote-fleet-render-smoke']),
863
+ _prevVisibleIds: new Set(['remote-fleet-render-smoke']),
864
+ _forceUpdateFrames: 0,
865
+ _textOverlayV2State: {
866
+ cards: new Map(),
867
+ passiveCandidateIds: new Set(['remote-fleet-render-smoke']),
868
+ layer: document.createElement('div')
869
+ },
870
+ requestAnimationWake(reason) {
871
+ this._lastAnimationWakeReason = reason;
872
+ this._animationWakeCount = Number(this._animationWakeCount || 0) + 1;
873
+ },
874
+ isAnimationLoopActive() {
875
+ return true;
876
+ }
877
+ };
878
+ manager.setModuleForTest(moduleRef);
849
879
 
850
880
  const { nodeShell, bodyView } = createRemoteFleetTemplateShell(document, focusedDevice.DeviceId);
851
881
  document.body.appendChild(nodeShell);
882
+ const monitorNode = buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches);
883
+ moduleRef.nodeObjectsById.set('remote-fleet-render-smoke', {
884
+ model: monitorNode,
885
+ currentType: 'CSS',
886
+ cssObject: {
887
+ visible: true,
888
+ element: nodeShell
889
+ }
890
+ });
891
+ document.body.appendChild(moduleRef._textOverlayV2State.layer);
852
892
 
853
- manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
893
+ manager.renderRemoteFleetMonitorForTest(bodyView, monitorNode);
854
894
 
855
895
  let cards = bodyView.querySelectorAll('article[data-device-id]');
856
896
  assert.equal(cards.length, connectedCount);
@@ -952,6 +992,16 @@ try {
952
992
  false,
953
993
  'binary Blob frame paint must not clear/fill the canvas before drawing');
954
994
 
995
+ const liveOverlayCard = document.createElement('div');
996
+ liveOverlayCard.dataset.nodeId = 'remote-fleet-render-smoke';
997
+ liveOverlayCard.dataset.sourceKind = 'live';
998
+ liveOverlayCard.dataset.liveInteractive = 'true';
999
+ liveOverlayCard.style.display = 'block';
1000
+ moduleRef._textOverlayV2State.cards.set('selection:remote-fleet-render-smoke', liveOverlayCard);
1001
+ moduleRef._forceUpdateFrames = 0;
1002
+ moduleRef._animationWakeCount = 0;
1003
+ moduleRef._lastAnimationWakeReason = '';
1004
+
955
1005
  await wait(20);
956
1006
  const liveWs = diagnostics.webSocketConnections[0];
957
1007
  assert.ok(liveWs, 'expected MDM render to open the binary frame WebSocket');
@@ -979,6 +1029,14 @@ try {
979
1029
  patchPreview.dataset.remoteFleetFrameSeq,
980
1030
  String(websocketFrameSeq),
981
1031
  JSON.stringify(diagnostics.runtimeTrace.slice(-12)));
1032
+ await wait(10);
1033
+ assert.ok(
1034
+ Number(moduleRef._forceUpdateFrames || 0) >= 2,
1035
+ 'binary live frame commits must wake the passive MDM overlay frame loop');
1036
+ assert.equal(moduleRef._lastAnimationWakeReason, 'remote-live-overlay-frame');
1037
+ assert.ok(
1038
+ diagnostics.runtimeTrace.some(event => event.type === 'remote.frame.overlayWake'),
1039
+ 'binary live frame commits must trace the MDM overlay wake path');
982
1040
 
983
1041
  manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
984
1042
  await wait(30);
@@ -997,6 +1055,111 @@ try {
997
1055
  assert.equal(rerenderedPatchPreview.dataset.remoteFleetFrameSeq, String(websocketFrameSeq));
998
1056
  assert.equal(rerenderedPatchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]')?.style.display, 'block');
999
1057
 
1058
+ const liveStartCallsBeforeControl = dotNetCalls.filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs').length;
1059
+ const sendCountBeforeControl = diagnostics.webSocketSends.length;
1060
+ const drawCountBeforeControl = document.canvasDrawCalls.length;
1061
+ const controlCard = bodyView.querySelector(`article[data-device-id="${patchTarget.DeviceId}"]`);
1062
+ assert.ok(controlCard);
1063
+ controlCard.dispatchEvent({ type: 'dblclick', button: 0 });
1064
+ await wait(30);
1065
+ const controlPopup = document.body.querySelector('[data-remote-fleet-control-popup="true"]');
1066
+ assert.ok(controlPopup, 'double-clicking an MDM tile should open the control popup');
1067
+ const controlShell = controlPopup.querySelector('[data-remote-fleet-control-shell="true"]');
1068
+ const controlStage = controlPopup.querySelector('[data-remote-fleet-control-stage="true"]');
1069
+ const controlCanvas = controlPopup.querySelector('[data-remote-fleet-control-canvas="true"]');
1070
+ assert.ok(controlShell);
1071
+ assert.ok(controlStage);
1072
+ assert.ok(controlCanvas);
1073
+ assert.equal(document.activeElement, controlShell);
1074
+ const controlStartCalls = dotNetCalls
1075
+ .filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs')
1076
+ .slice(liveStartCallsBeforeControl);
1077
+ assert.equal(controlStartCalls.length, 1);
1078
+ assert.equal(controlStartCalls[0].args[0], 'remote-fleet-render-smoke');
1079
+ assert.equal(controlStartCalls[0].args[1], patchTarget.DeviceId);
1080
+ assert.equal(controlStartCalls[0].args[2], 20);
1081
+ const controlSubscribe = diagnostics.webSocketSends
1082
+ .slice(sendCountBeforeControl)
1083
+ .map(send => {
1084
+ try {
1085
+ return JSON.parse(send.payload);
1086
+ } catch {
1087
+ return null;
1088
+ }
1089
+ })
1090
+ .find(message =>
1091
+ message
1092
+ && message.type === 'subscribe'
1093
+ && message.nodeId === 'remote-fleet-render-smoke'
1094
+ && message.autoStartLive === true
1095
+ && message.fps === 20
1096
+ && Array.isArray(message.deviceIds)
1097
+ && message.deviceIds.includes(patchTarget.DeviceId));
1098
+ assert.ok(controlSubscribe, 'control popup should reuse the binary frame WebSocket with a 20fps subscription');
1099
+
1100
+ const controlFrameSeq = 20001;
1101
+ liveWs.onmessage?.({
1102
+ data: new Blob([encodeRemoteBinaryFrame({
1103
+ type: 'remote.frame.binary',
1104
+ deviceId: patchTarget.DeviceId,
1105
+ kind: 'live',
1106
+ frameSeq: controlFrameSeq,
1107
+ streamId: 'render-smoke-control-live',
1108
+ contentHash: `render-smoke-control-live-${controlFrameSeq}`,
1109
+ mimeType: 'image/jpeg',
1110
+ width: 64,
1111
+ height: 36,
1112
+ capturedAt: new Date().toISOString(),
1113
+ receivedAt: new Date().toISOString()
1114
+ })])
1115
+ });
1116
+ await wait(40);
1117
+ assert.equal(controlCanvas.style.display, 'block');
1118
+ assert.ok(
1119
+ document.canvasDrawCalls
1120
+ .slice(drawCountBeforeControl)
1121
+ .some(call => call.canvas === controlCanvas && call.op === 'drawImage'),
1122
+ 'control popup should paint binary WebSocket frames directly to its canvas');
1123
+
1124
+ controlStage.dispatchEvent({
1125
+ type: 'pointerdown',
1126
+ button: 0,
1127
+ pointerId: 7,
1128
+ clientX: 160,
1129
+ clientY: 90
1130
+ });
1131
+ controlStage.dispatchEvent({
1132
+ type: 'pointerup',
1133
+ button: 0,
1134
+ pointerId: 7,
1135
+ clientX: 160,
1136
+ clientY: 90
1137
+ });
1138
+ controlShell.dispatchEvent({
1139
+ type: 'keydown',
1140
+ key: 'A',
1141
+ code: 'KeyA',
1142
+ repeat: false
1143
+ });
1144
+ await wait(20);
1145
+ const inputCalls = dotNetCalls.filter(call => call.methodName === 'SendRemoteFleetInputFromJs');
1146
+ assert.ok(inputCalls.length >= 3, 'control popup should send pointer and keyboard input through JS interop');
1147
+ const pointerDown = inputCalls.find(call => call.args[2]?.type === 'pointerDown');
1148
+ const keyDown = inputCalls.find(call => call.args[2]?.type === 'keyDown');
1149
+ assert.ok(pointerDown);
1150
+ assert.ok(keyDown);
1151
+ assert.equal(pointerDown.args[0], 'remote-fleet-render-smoke');
1152
+ assert.equal(pointerDown.args[1], patchTarget.DeviceId);
1153
+ assert.equal(pointerDown.args[2].button, 'left');
1154
+ assert.ok(pointerDown.args[2].controlLeaseId);
1155
+ assert.ok(pointerDown.args[2].normalizedX >= 0 && pointerDown.args[2].normalizedX <= 1);
1156
+ assert.ok(pointerDown.args[2].normalizedY >= 0 && pointerDown.args[2].normalizedY <= 1);
1157
+ assert.equal(keyDown.args[2].key, 'A');
1158
+ assert.equal(keyDown.args[2].code, 'KeyA');
1159
+ manager.closeRemoteFleetControlPopupForTest('render-smoke');
1160
+ await wait(20);
1161
+ assert.equal(document.body.querySelector('[data-remote-fleet-control-popup="true"]'), null);
1162
+
1000
1163
  const alternateDevice = devices.find(device =>
1001
1164
  device.Connected === true
1002
1165
  && device.DeviceId !== focusedDevice.DeviceId);
@@ -1063,7 +1226,9 @@ try {
1063
1226
  assert.equal(resultPanel, null);
1064
1227
  assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
1065
1228
  await wait(20);
1066
- const liveStartCalls = dotNetCalls.filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs');
1229
+ const liveStartCalls = dotNetCalls
1230
+ .filter(call => call.methodName === 'StartRemoteFleetLiveStreamFromJs')
1231
+ .slice(0, liveStartCallsBeforeControl);
1067
1232
  const subscribeMessages = diagnostics.webSocketSends
1068
1233
  .map(send => {
1069
1234
  try {
@@ -13877,6 +13877,145 @@
13877
13877
  : 0;
13878
13878
  }
13879
13879
 
13880
+ function getRemoteFleetBodyNodeId(bodyView) {
13881
+ return String(
13882
+ bodyView?.dataset?.nodeId
13883
+ || bodyView?.dataset?.remoteFleetMonitorNodeId
13884
+ || bodyView?.closest?.('.map-node-remote-fleet__body[data-node-id]')?.dataset?.nodeId
13885
+ || bodyView?.closest?.('[data-node-id]')?.dataset?.nodeId
13886
+ || ''
13887
+ ).trim();
13888
+ }
13889
+
13890
+ function getRemoteFleetBodyFromPreview(preview) {
13891
+ if (!preview) {
13892
+ return null;
13893
+ }
13894
+
13895
+ return preview.closest?.('.map-node-remote-fleet__body[data-node-id]')
13896
+ || preview.closest?.('.map-node-remote-fleet__body[data-remote-fleet-monitor-node-id]')
13897
+ || null;
13898
+ }
13899
+
13900
+ function wakeRemoteFleetModuleAnimation(module, reason) {
13901
+ if (!module) {
13902
+ return;
13903
+ }
13904
+
13905
+ if (typeof module.requestAnimationWake === 'function') {
13906
+ module.requestAnimationWake(reason);
13907
+ }
13908
+
13909
+ if (typeof module.isAnimationLoopActive === 'function'
13910
+ && module.isAnimationLoopActive() !== true
13911
+ && typeof module.animate === 'function') {
13912
+ module.animate();
13913
+ }
13914
+ }
13915
+
13916
+ function flushRemoteFleetLiveOverlayWake(module) {
13917
+ const state = module?._remoteFleetLiveOverlayWakeState || null;
13918
+ if (!module || !state || !(state.nodeIds instanceof Set)) {
13919
+ return;
13920
+ }
13921
+
13922
+ state.raf = 0;
13923
+ let woke = false;
13924
+ const overlayState = module._textOverlayV2State || null;
13925
+ state.nodeIds.forEach(nodeId => {
13926
+ const normalizedNodeId = String(nodeId || '').trim();
13927
+ if (!normalizedNodeId) {
13928
+ return;
13929
+ }
13930
+
13931
+ const entry = module.nodeObjectsById?.get?.(normalizedNodeId) || null;
13932
+ if (!entry?.model || !isRemoteFleetMonitorNode(entry.model)) {
13933
+ return;
13934
+ }
13935
+
13936
+ const card = overlayState?.cards?.get?.(`selection:${normalizedNodeId}`) || null;
13937
+ const hasLiveOverlayCard =
13938
+ !!card &&
13939
+ card.style?.display !== 'none' &&
13940
+ card.dataset?.sourceKind === 'live' &&
13941
+ card.dataset?.liveInteractive === 'true';
13942
+ const mayCreatePassiveOverlay =
13943
+ window.MindMapTextOverlayV2?.shouldRenderPassiveDomOverlays?.(module) === true &&
13944
+ (
13945
+ overlayState?.passiveCandidateIds?.has?.(normalizedNodeId) === true ||
13946
+ module._visibleIds?.has?.(normalizedNodeId) === true ||
13947
+ module._prevVisibleIds?.has?.(normalizedNodeId) === true ||
13948
+ String(module.selectedNodeIdJs || '').trim() === normalizedNodeId
13949
+ );
13950
+
13951
+ if (!hasLiveOverlayCard && !mayCreatePassiveOverlay) {
13952
+ return;
13953
+ }
13954
+
13955
+ if (hasLiveOverlayCard) {
13956
+ if (overlayState?.layer?.style && module._suppressPassiveDomOverlayDuringZoom !== true) {
13957
+ overlayState.layer.style.display = '';
13958
+ }
13959
+ card.style.display = 'block';
13960
+ } else {
13961
+ window.MindMapTextOverlayV2?.invalidateNode?.(module, normalizedNodeId, 'remote-live-frame');
13962
+ module._overlayDirty = true;
13963
+ module._lastOverlayKey = '';
13964
+ }
13965
+
13966
+ woke = true;
13967
+ });
13968
+ state.nodeIds.clear();
13969
+
13970
+ if (!woke) {
13971
+ return;
13972
+ }
13973
+
13974
+ module._forceUpdateFrames = Math.max(Number(module._forceUpdateFrames || 0), 2);
13975
+ module._css3dVisualChangedThisFrame = true;
13976
+ module._css3dVisualChangedSinceLastRender = true;
13977
+ wakeRemoteFleetModuleAnimation(module, 'remote-live-overlay-frame');
13978
+
13979
+ const now = getRemoteFleetFrameNow();
13980
+ if (now - Number(module._remoteFleetLiveOverlayWakeLastTraceAt || 0) >= 1000) {
13981
+ module._remoteFleetLiveOverlayWakeLastTraceAt = now;
13982
+ window.RuntimeTrace?.emit?.('remote.frame.overlayWake', {
13983
+ nodes: state.lastWakeCount || 0
13984
+ });
13985
+ }
13986
+ }
13987
+
13988
+ function requestRemoteFleetLiveOverlayWake(bodyView, frame) {
13989
+ if (!_module || !bodyView || String(frame?.kind || '').toLowerCase() !== 'live') {
13990
+ return false;
13991
+ }
13992
+
13993
+ const nodeId = getRemoteFleetBodyNodeId(bodyView);
13994
+ if (!nodeId) {
13995
+ return false;
13996
+ }
13997
+
13998
+ const state = _module._remoteFleetLiveOverlayWakeState || {
13999
+ nodeIds: new Set(),
14000
+ raf: 0,
14001
+ lastWakeCount: 0
14002
+ };
14003
+ _module._remoteFleetLiveOverlayWakeState = state;
14004
+ state.nodeIds.add(nodeId);
14005
+ state.lastWakeCount = state.nodeIds.size;
14006
+
14007
+ if (!state.raf) {
14008
+ state.raf = requestRemoteFleetFrameLoopFrame(() => flushRemoteFleetLiveOverlayWake(_module));
14009
+ }
14010
+
14011
+ return true;
14012
+ }
14013
+
14014
+ function requestRemoteFleetLiveOverlayWakeFromPreview(preview, frame) {
14015
+ const bodyView = getRemoteFleetBodyFromPreview(preview);
14016
+ return requestRemoteFleetLiveOverlayWake(bodyView, frame);
14017
+ }
14018
+
13880
14019
  function refreshRemoteFleetBinaryFrameSubscription(session, force = false) {
13881
14020
  if (!session?.ws || session.ws.readyState !== WebSocket.OPEN) {
13882
14021
  return false;
@@ -14701,7 +14840,11 @@
14701
14840
  canvas.style.display = 'none';
14702
14841
  }
14703
14842
 
14704
- return commitRemoteFleetFrameMetadata(preview, frame);
14843
+ const committed = commitRemoteFleetFrameMetadata(preview, frame);
14844
+ if (committed) {
14845
+ requestRemoteFleetLiveOverlayWakeFromPreview(preview, frame);
14846
+ }
14847
+ return committed;
14705
14848
  }
14706
14849
 
14707
14850
  function commitRemoteFleetFrameToCanvas(preview, canvas, image, bitmap, frame) {
@@ -14722,7 +14865,11 @@
14722
14865
  image.style.display = 'none';
14723
14866
  }
14724
14867
 
14725
- return commitRemoteFleetFrameMetadata(preview, frame);
14868
+ const committed = commitRemoteFleetFrameMetadata(preview, frame);
14869
+ if (committed) {
14870
+ requestRemoteFleetLiveOverlayWakeFromPreview(preview, frame);
14871
+ }
14872
+ return committed;
14726
14873
  }
14727
14874
 
14728
14875
  function clearRemoteFleetPendingFrameDataset(preview, frame) {
@@ -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-mdm-ws-rerender-v580" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-mdm-ws-rerender-v580" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260617-mdm-overlay-live-v581" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-mdm-overlay-live-v581" />
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-mdm-ws-rerender-v580';
582
+ const scriptVersion = '20260617-mdm-overlay-live-v581';
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": "caOR4cJE",
2
+ "version": "oR91p21X",
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-ct4yGB6E/ViQSpNNn3fHtt3v+usCW9LYQEbpOmzuRdk=",
89
+ "hash": "sha256-+Y65YIk5GcFioFxM72xcAvkC2+vdx+B90L2qlalXrhw=",
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-zI55TuKnPpHEJMEolp25Zk/P6dkZEOtbMSHObMgR84A=",
837
+ "hash": "sha256-6kgfFKKW8vB1esatu6Iq0af4n6evMTxQfK5SCVpyq5k=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: caOR4cJE */
1
+ /* Manifest version: oR91p21X */
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