@mindexec/cli 0.2.171 → 0.2.172

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.171",
3
+ "version": "0.2.172",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -164,7 +164,7 @@ async function connectManagedAgent(clientBridge, managerEndpoint, staleEndpoint)
164
164
  leaseId: LEASE_ID,
165
165
  nodeId: 'remote-agent-managed-smoke-node',
166
166
  engine: 'auto',
167
- source: 'smoke'
167
+ source: 'local-bridge-registry'
168
168
  })
169
169
  });
170
170
 
@@ -247,6 +247,32 @@ async function main() {
247
247
  assert.equal(secondAgent.managerCandidates?.[0], managerEndpoint, JSON.stringify(secondAgent.managerCandidates));
248
248
  assert.equal(secondAgent.managerCandidates?.[1], staleEndpoint, JSON.stringify(secondAgent.managerCandidates));
249
249
 
250
+ const staleReport = await fetchJson(`${clientBridge.baseUrl}/api/remote/agent/sync-report`, {
251
+ method: 'POST',
252
+ body: JSON.stringify({
253
+ ok: false,
254
+ attempted: true,
255
+ disconnected: true,
256
+ authenticated: true,
257
+ reason: 'agent-disconnected',
258
+ targetActive: true,
259
+ targetEndpoint: managerEndpoint,
260
+ targetEndpointCandidates: [managerEndpoint, staleEndpoint],
261
+ targetLeaseId: LEASE_ID,
262
+ targetNodeId: 'remote-agent-managed-smoke-node'
263
+ })
264
+ });
265
+ assert.equal(staleReport.ok, true, JSON.stringify(staleReport.payload));
266
+
267
+ const staleState = await fetchJson(`${clientBridge.baseUrl}/api/remote/agent/status`);
268
+ assert.equal(staleState.payload?.needsReconnect, true, JSON.stringify(staleState.payload));
269
+
270
+ const thirdAgent = await connectManagedAgent(clientBridge, managerEndpoint, staleEndpoint);
271
+ assert.equal(thirdAgent.running, true, JSON.stringify(thirdAgent));
272
+ assert.equal(thirdAgent.ready, true, JSON.stringify(thirdAgent));
273
+ assert.equal(thirdAgent.needsReconnect, false, JSON.stringify(thirdAgent));
274
+ assert.notEqual(thirdAgent.pid, secondAgent.pid, `stale registry-owned RemoteAgent should be restarted, second=${secondAgent.pid}, third=${thirdAgent.pid}`);
275
+
250
276
  console.log('RemoteAgent managed supervisor smoke OK');
251
277
  } finally {
252
278
  if (hangingManager) {
@@ -964,14 +964,11 @@ try {
964
964
  assert.match(bodyView.querySelector('[data-remote-fleet-device-grid="true"]')?.style.cssText || '', /minmax\(297px,\s*1fr\)/);
965
965
  assert.equal(mirrorBodyView.dataset.remoteFleetDensity, 'large');
966
966
  assert.match(mirrorBodyView.querySelector('[data-remote-fleet-device-grid="true"]')?.style.cssText || '', /minmax\(297px,\s*1fr\)/);
967
- assert.ok(diagnostics.textOverlayInvalidations.some(entry =>
968
- entry.nodeId === 'remote-fleet-render-smoke'
969
- && entry.reason === 'remote-monitor-size'));
970
967
  assert.ok(diagnostics.runtimeTrace.some(entry =>
971
968
  entry.type === 'remote.monitor.sizeChanged'
972
969
  && entry.nodeId === 'remote-fleet-render-smoke'
973
970
  && entry.density === 'large'
974
- && entry.overlayInvalidated === true));
971
+ && entry.css3dOnly === true));
975
972
  bodyView.querySelector('[data-remote-fleet-action="monitor-size-down"]').dispatchEvent({ type: 'click' });
976
973
  assert.equal(bodyView.dataset.remoteFleetDensity, 'cards');
977
974
  assert.match(bodyView.querySelector('[data-remote-fleet-device-grid="true"]')?.style.cssText || '', /minmax\(198px,\s*1fr\)/);
@@ -987,21 +984,30 @@ try {
987
984
  cards = bodyView.querySelectorAll('article[data-device-id]');
988
985
  const patchTarget = devices.find(device =>
989
986
  device.Connected === true
990
- && device.ThumbnailEnabled === true
991
- && device.LiveStreamActive !== true);
987
+ && device.ThumbnailEnabled === true);
992
988
  assert.ok(patchTarget);
993
989
  const patchCard = Array.from(cards).find(card => card.dataset.deviceId === patchTarget.DeviceId);
994
990
  const patchPreview = patchCard?.querySelector('[data-remote-fleet-device-preview="tile"]');
995
991
  assert.ok(patchPreview);
996
- const patchUrl = `/api/remote/devices/${encodeURIComponent(patchTarget.DeviceId)}/thumbnail?token=render-smoke-frame&seq=9999`;
992
+ const patchKind = String(patchPreview.dataset.remoteFleetFrameKind || '').toLowerCase() === 'live'
993
+ ? 'live'
994
+ : 'thumbnail';
995
+ const patchUrl = `/api/remote/devices/${encodeURIComponent(patchTarget.DeviceId)}/${patchKind}?token=render-smoke-frame&seq=9999`;
997
996
  const patchCount = manager.applyRemoteFleetFramePatchesForTest(bodyView, [{
998
997
  deviceId: patchTarget.DeviceId,
999
- kind: 'thumbnail',
998
+ kind: patchKind,
1000
999
  frameSeq: 9999,
1001
1000
  frameUrl: patchUrl,
1002
1001
  receivedAt: new Date().toISOString()
1003
1002
  }]);
1004
- assert.equal(patchCount, 1);
1003
+ assert.equal(patchCount, 1, JSON.stringify({
1004
+ targetDeviceId: patchTarget.DeviceId,
1005
+ previewCount: bodyView.querySelectorAll('[data-remote-fleet-device-preview]').length,
1006
+ previewIds: Array.from(bodyView.querySelectorAll('[data-remote-fleet-device-preview]')).slice(0, 12).map(preview => preview.dataset.deviceId || ''),
1007
+ currentKind: patchPreview.dataset.remoteFleetFrameKind || '',
1008
+ currentSeq: patchPreview.dataset.remoteFleetFrameSeq || '',
1009
+ currentUrl: patchPreview.dataset.remoteFleetFrameUrl || ''
1010
+ }));
1005
1011
  await wait();
1006
1012
  assert.equal(patchPreview.dataset.remoteFleetFrameSeq, '9999');
1007
1013
  assert.equal(patchPreview.dataset.remoteFleetFrameUrl, patchUrl);
@@ -1085,11 +1091,11 @@ try {
1085
1091
  await wait(10);
1086
1092
  assert.ok(
1087
1093
  Number(moduleRef._forceUpdateFrames || 0) >= 2,
1088
- 'binary live frame commits must wake the passive MDM overlay frame loop');
1089
- assert.equal(moduleRef._lastAnimationWakeReason, 'remote-live-overlay-frame');
1094
+ 'binary live frame commits must wake the passive MDM CSS3D frame loop');
1095
+ assert.equal(moduleRef._lastAnimationWakeReason, 'remote-live-css3d-frame');
1090
1096
  assert.ok(
1091
- diagnostics.runtimeTrace.some(event => event.type === 'remote.frame.overlayWake'),
1092
- 'binary live frame commits must trace the MDM overlay wake path');
1097
+ diagnostics.runtimeTrace.some(event => event.type === 'remote.frame.css3dWake'),
1098
+ 'binary live frame commits must trace the MDM CSS3D wake path');
1093
1099
 
1094
1100
  manager.renderRemoteFleetMonitorForTest(bodyView, buildMonitorNode(devices, hub.getStatus({ includeSecrets: true }), latestTaskBatch, recentTaskBatches));
1095
1101
  await wait(30);
@@ -1139,7 +1145,7 @@ try {
1139
1145
  otherBoardPatchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]')?.style.display,
1140
1146
  'block');
1141
1147
  assert.ok(diagnostics.runtimeTrace.some(event =>
1142
- event.type === 'remote.frame.wsCachePrimed'
1148
+ (event.type === 'remote.frame.wsCachePrimed' || event.type === 'remote.frame.surfaceCachePrimed')
1143
1149
  && event.nodeId === otherBoardNodeId));
1144
1150
  otherBoardShell.remove();
1145
1151
 
@@ -1194,14 +1200,11 @@ try {
1194
1200
  assert.equal(hostFeedback?.textContent, '');
1195
1201
  assert.equal(nodeShell.querySelector('[data-remote-fleet-host-indicator="true"]')?.dataset.remoteFleetHostActive, 'true');
1196
1202
  assert.equal(hostMirrorShell.querySelector('[data-remote-fleet-host-indicator="true"]')?.dataset.remoteFleetHostActive, 'true');
1197
- assert.ok(diagnostics.textOverlayInvalidations.some(entry =>
1198
- entry.nodeId === 'remote-fleet-render-smoke'
1199
- && entry.reason === 'remote-monitor-host'));
1200
1203
  assert.ok(diagnostics.runtimeTrace.some(entry =>
1201
1204
  entry.type === 'remote.monitor.projectionInvalidated'
1202
1205
  && entry.nodeId === 'remote-fleet-render-smoke'
1203
1206
  && entry.reason === 'host'
1204
- && entry.overlayInvalidated === true));
1207
+ && entry.css3dOnly === true));
1205
1208
  hostMirrorShell.remove();
1206
1209
 
1207
1210
  hub.setHostTarget({
package/server.js CHANGED
@@ -3493,6 +3493,8 @@ function createRemoteAgentIdleState(overrides = {}) {
3493
3493
  updatedAt: new Date().toISOString(),
3494
3494
  ready: false,
3495
3495
  connectedAt: '',
3496
+ needsReconnect: false,
3497
+ reconnectReason: '',
3496
3498
  exitedAt: '',
3497
3499
  exitCode: null,
3498
3500
  signal: '',
@@ -3548,6 +3550,90 @@ function createRemoteAgentSyncReport(body = {}) {
3548
3550
  };
3549
3551
  }
3550
3552
 
3553
+ function isRemoteAgentSyncReportReconnectSignal(report) {
3554
+ if (!report || report.connected === true) {
3555
+ return false;
3556
+ }
3557
+
3558
+ const reason = String(report.reason || '').toLowerCase();
3559
+ const error = String(report.error || '').toLowerCase();
3560
+ const text = `${reason} ${error}`.trim();
3561
+ if (!text && report.disconnected !== true) {
3562
+ return false;
3563
+ }
3564
+
3565
+ if (/(throttled|registry-not-authenticated|registry-auth-pending|session-expired|no-active-target|registry-inactive|local-monitor-is-host|local-host-superseded|same-host|target-missing-endpoint-or-pair)/i.test(text)) {
3566
+ return false;
3567
+ }
3568
+
3569
+ return report.disconnected === true
3570
+ || /(agent-(disconnected|exited|failed)|connect-failed|connection-(closed|lost|reset)|socket-(closed|reset)|econnreset|read econnreset|ws-close|websocket.*close)/i.test(text);
3571
+ }
3572
+
3573
+ function isRemoteAgentSyncReportForManagers(report, managers = [], leaseId = '') {
3574
+ if (!report) {
3575
+ return false;
3576
+ }
3577
+
3578
+ const reportLeaseId = safeRemoteAgentField(report.targetLeaseId, 128);
3579
+ const targetLeaseId = safeRemoteAgentField(leaseId, 128);
3580
+ if (reportLeaseId && targetLeaseId && reportLeaseId !== targetLeaseId) {
3581
+ return false;
3582
+ }
3583
+
3584
+ const reportManagers = normalizeRemoteManagerEndpointList(report.targetEndpointCandidates, report.targetEndpoint);
3585
+ const targetManagers = normalizeRemoteManagerEndpointList(managers);
3586
+ if (reportManagers.length === 0 || targetManagers.length === 0) {
3587
+ return true;
3588
+ }
3589
+
3590
+ const targetSet = new Set(targetManagers.map(value => value.toLowerCase()));
3591
+ return reportManagers.some(value => targetSet.has(value.toLowerCase()));
3592
+ }
3593
+
3594
+ function shouldRestartRemoteAgentForTarget(managers = [], leaseId = '') {
3595
+ if (!isRemoteAgentProcessRunning()) {
3596
+ return false;
3597
+ }
3598
+
3599
+ const activeConnectionKeys = new Set(
3600
+ normalizeRemoteManagerEndpointList(managers).map(manager => createRemoteAgentConnectionKey(manager, leaseId))
3601
+ );
3602
+ if (activeConnectionKeys.size > 0 && !activeConnectionKeys.has(remoteAgentState.connectionKey)) {
3603
+ return false;
3604
+ }
3605
+
3606
+ if (remoteAgentState.needsReconnect === true) {
3607
+ return true;
3608
+ }
3609
+
3610
+ return isRemoteAgentRegistryOwned()
3611
+ && isRemoteAgentSyncReportReconnectSignal(remoteAgentSyncReportState)
3612
+ && isRemoteAgentSyncReportForManagers(remoteAgentSyncReportState, managers, leaseId);
3613
+ }
3614
+
3615
+ function markRemoteAgentReconnectNeededFromReport(report) {
3616
+ if (!isRemoteAgentRegistryOwned()
3617
+ || !isRemoteAgentSyncReportReconnectSignal(report)
3618
+ || !isRemoteAgentSyncReportForManagers(report, remoteAgentState.managerCandidates, remoteAgentState.leaseId)) {
3619
+ return false;
3620
+ }
3621
+
3622
+ const reason = safeRemoteAgentField(report.reason || report.error || 'sync-report-disconnected', 160);
3623
+ if (remoteAgentState.needsReconnect !== true) {
3624
+ logWarn(
3625
+ 'remote',
3626
+ `managed RemoteAgent marked stale from sync report ${formatKeyValue('reason', reason)} ${formatKeyValue('manager', remoteAgentState.manager || '-')}`);
3627
+ }
3628
+ remoteAgentState.needsReconnect = true;
3629
+ remoteAgentState.reconnectReason = reason;
3630
+ remoteAgentState.lastError = reason;
3631
+ remoteAgentState.updatedAt = new Date().toISOString();
3632
+ emitBridgeEvent('RemoteAgentNeedsReconnect', serializeRemoteAgentState());
3633
+ scheduleRemoteRegistryFollower(0, 'agent-sync-report-disconnected');
3634
+ return true;
3635
+ }
3636
+
3551
3637
  function rememberRemoteAgentSyncReport(report) {
3552
3638
  remoteAgentSyncReportState = report;
3553
3639
  const reason = report.reason || report.error || (report.ok ? 'ok' : 'failed');
@@ -3559,9 +3645,10 @@ function rememberRemoteAgentSyncReport(report) {
3559
3645
  ? 'attempted'
3560
3646
  : report.skipped
3561
3647
  ? 'skipped'
3562
- : report.ok
3563
- ? 'ok'
3564
- : 'failed';
3648
+ : report.ok
3649
+ ? 'ok'
3650
+ : 'failed';
3651
+ markRemoteAgentReconnectNeededFromReport(report);
3565
3652
  const key = [
3566
3653
  status,
3567
3654
  reason,
@@ -3597,6 +3684,8 @@ function appendRemoteAgentOutput(stream, chunk, stateConnectionKey = '') {
3597
3684
  if (/Connected to RemoteHub/i.test(text)) {
3598
3685
  remoteAgentState.ready = true;
3599
3686
  remoteAgentState.connectedAt = new Date().toISOString();
3687
+ remoteAgentState.needsReconnect = false;
3688
+ remoteAgentState.reconnectReason = '';
3600
3689
  }
3601
3690
  remoteAgentState.updatedAt = new Date().toISOString();
3602
3691
  }
@@ -4326,6 +4415,19 @@ async function startRemoteAgentConnection(options = {}) {
4326
4415
  }
4327
4416
 
4328
4417
  const activeConnectionKeys = new Set(managers.map(manager => createRemoteAgentConnectionKey(manager, leaseId)));
4418
+ if (isRemoteAgentProcessRunning()
4419
+ && activeConnectionKeys.has(remoteAgentState.connectionKey)) {
4420
+ if (shouldRestartRemoteAgentForTarget(managers, leaseId)) {
4421
+ const reason = remoteAgentState.reconnectReason || remoteAgentState.lastError || 'registry-agent-stale';
4422
+ logWarn(
4423
+ 'remote',
4424
+ `managed RemoteAgent restarting stale registry process ${formatKeyValue('manager', remoteAgentState.manager || managers[0])} ${formatKeyValue('reason', reason)}`);
4425
+ await stopRemoteAgentConnection('registry-agent-stale', { suppressRetry: false });
4426
+ } else {
4427
+ return { ok: true, alreadyRunning: true, agent: serializeRemoteAgentState() };
4428
+ }
4429
+ }
4430
+
4329
4431
  if (isRemoteAgentProcessRunning()
4330
4432
  && activeConnectionKeys.has(remoteAgentState.connectionKey)) {
4331
4433
  return { ok: true, alreadyRunning: true, agent: serializeRemoteAgentState() };
@@ -4378,6 +4480,8 @@ function appendRemoteAgentAttemptOutput(attempt, stream, chunk) {
4378
4480
  if (/Connected to RemoteHub/i.test(text)) {
4379
4481
  attempt.state.ready = true;
4380
4482
  attempt.state.connectedAt = new Date().toISOString();
4483
+ attempt.state.needsReconnect = false;
4484
+ attempt.state.reconnectReason = '';
4381
4485
  }
4382
4486
  attempt.state.updatedAt = new Date().toISOString();
4383
4487
  }
@@ -4625,6 +4729,8 @@ async function startRemoteAgentConnectionRace(options = {}) {
4625
4729
  remoteAgentState = winner.state;
4626
4730
  remoteAgentState.status = 'running';
4627
4731
  remoteAgentState.proc = winner.child;
4732
+ remoteAgentState.needsReconnect = false;
4733
+ remoteAgentState.reconnectReason = '';
4628
4734
  remoteAgentState.updatedAt = new Date().toISOString();
4629
4735
  rememberRemoteAgentSuccessfulManager(winner.manager, leaseId);
4630
4736
  emitBridgeEvent('RemoteAgentStarted', serializeRemoteAgentState());
@@ -14864,7 +14864,7 @@
14864
14864
  return surfaces;
14865
14865
  }
14866
14866
 
14867
- root.querySelectorAll('[data-remote-fleet-device-preview][data-device-id]').forEach(preview => {
14867
+ root.querySelectorAll('[data-remote-fleet-device-preview]').forEach(preview => {
14868
14868
  const deviceId = String(preview.dataset.deviceId || '').trim();
14869
14869
  if (!deviceId) {
14870
14870
  return;
@@ -15823,13 +15823,15 @@
15823
15823
 
15824
15824
  function getRemoteFleetFramePatchTargets(bodyView) {
15825
15825
  const targets = [];
15826
- const addTarget = target => {
15827
- if (target && document.body.contains(target) && !targets.includes(target)) {
15826
+ const addTarget = (target, requireAttached = true) => {
15827
+ if (target
15828
+ && (!requireAttached || document.body.contains(target))
15829
+ && !targets.includes(target)) {
15828
15830
  targets.push(target);
15829
15831
  }
15830
15832
  };
15831
15833
 
15832
- addTarget(bodyView);
15834
+ addTarget(bodyView, false);
15833
15835
  const nodeId = String(bodyView?.dataset?.nodeId || '').trim();
15834
15836
  if (nodeId) {
15835
15837
  document.querySelectorAll('.map-node-remote-fleet__body[data-node-id]').forEach(candidate => {
@@ -15855,7 +15857,8 @@
15855
15857
  const frameKind = String(frame.kind || '').toLowerCase();
15856
15858
 
15857
15859
  targets.forEach(target => {
15858
- target.querySelectorAll('[data-remote-fleet-device-preview][data-device-id]').forEach(preview => {
15860
+ target.querySelectorAll('[data-remote-fleet-device-preview]').forEach(preview => {
15861
+ if (!preview.dataset.deviceId) return;
15859
15862
  if (String(preview.dataset.deviceId || '').trim() !== deviceId) return;
15860
15863
  const currentKind = String(preview.dataset.remoteFleetFrameKind || '').toLowerCase();
15861
15864
  if (currentKind === 'live' && frameKind !== 'live') return;
@@ -22228,7 +22231,8 @@
22228
22231
  background: transparent;
22229
22232
  `;
22230
22233
 
22231
- const size = 18;
22234
+ const remoteFleetSurface = isRemoteFleetMonitorNode(nodeModel) || isRemoteFleetDeviceNode(nodeModel);
22235
+ const size = remoteFleetSurface ? 26 : 18;
22232
22236
  const edgeOffset = `${size}px`;
22233
22237
  const zones = [
22234
22238
  { corner: 'TL', className: 'nw', cursor: 'nwse-resize', style: `left:0;top:0;width:${size}px;height:${size}px;` },
@@ -59,6 +59,65 @@
59
59
  };
60
60
  }
61
61
 
62
+ function syncRemoteFleetCss3dResizeSurface(nodeEntry, options = {}) {
63
+ if (!nodeEntry?.cssObject?.element || !isRemoteFleetMonitorNodeModel(nodeEntry.model)) {
64
+ return;
65
+ }
66
+
67
+ const model = nodeEntry.model;
68
+ const cssObject = nodeEntry.cssObject;
69
+ const worldWidth = Math.max(REMOTE_FLEET_MONITOR_MIN_WIDTH, Number(model.width || model.Width || 0) || REMOTE_FLEET_MONITOR_MIN_WIDTH);
70
+ const worldHeight = Math.max(REMOTE_FLEET_MONITOR_MIN_HEIGHT, Number(model.height || model.Height || 0) || REMOTE_FLEET_MONITOR_MIN_HEIGHT);
71
+ const resolutionScale = cssObject.userData?.resolutionScale || 1;
72
+ const wrapper = cssObject.element;
73
+ const domWidth = worldWidth * resolutionScale;
74
+ const domHeight = worldHeight * resolutionScale;
75
+
76
+ wrapper.style.width = `${domWidth}px`;
77
+ wrapper.style.height = `${domHeight}px`;
78
+ wrapper.style.minWidth = `${domWidth}px`;
79
+ wrapper.style.minHeight = `${domHeight}px`;
80
+ wrapper.style.maxWidth = `${domWidth}px`;
81
+ wrapper.style.maxHeight = `${domHeight}px`;
82
+
83
+ const card = wrapper.matches?.('.map-node-template-card.map-node-remote-fleet')
84
+ ? wrapper
85
+ : wrapper.querySelector?.('.map-node-template-card.map-node-remote-fleet');
86
+ if (card) {
87
+ card.style.width = `${worldWidth}px`;
88
+ card.style.height = `${worldHeight}px`;
89
+ card.style.minWidth = `${worldWidth}px`;
90
+ card.style.minHeight = `${worldHeight}px`;
91
+ card.style.maxWidth = `${worldWidth}px`;
92
+ card.style.maxHeight = `${worldHeight}px`;
93
+ card.style.boxSizing = 'border-box';
94
+ card.style.overflow = 'hidden';
95
+
96
+ const shell = card.querySelector('.template-card__shell--remote-fleet');
97
+ if (shell) {
98
+ shell.style.height = '100%';
99
+ shell.style.minHeight = '0';
100
+ shell.style.boxSizing = 'border-box';
101
+ }
102
+
103
+ const bodyView = card.querySelector('.template-card__remote-fleet-body');
104
+ if (bodyView) {
105
+ bodyView.style.flex = '1 1 auto';
106
+ bodyView.style.minHeight = '0';
107
+ bodyView.style.overflow = 'hidden';
108
+ }
109
+ }
110
+
111
+ if (cssObject.userData) {
112
+ cssObject.userData.worldWidth = worldWidth;
113
+ cssObject.userData.worldHeight = worldHeight;
114
+ }
115
+
116
+ if (options.render === true) {
117
+ window.MindMapCss3DManager?.syncCss3dContent?.(model, cssObject);
118
+ }
119
+ }
120
+
62
121
  function isDocumentHidden() {
63
122
  return typeof document !== 'undefined' && document.visibilityState === 'hidden';
64
123
  }
@@ -1228,10 +1287,11 @@
1228
1287
  // ▲▲▲ [Fix] ▲▲▲
1229
1288
  }
1230
1289
 
1231
- // ▼▼▼ [Fix] userData도 업데이트하여 syncCss3dContent에서 올바른 크기 사용 ▼▼▼
1290
+ // ▼▼▼ [Fix] userData도 업데이트하여 syncCss3dContent에서 올바른 크기 사용 ▼▼▼
1232
1291
  nodeEntry.cssObject.userData.worldWidth = nodeEntry.model.width;
1233
1292
  nodeEntry.cssObject.userData.worldHeight = nodeEntry.model.height;
1234
1293
  // ▲▲▲ [Fix] ▲▲▲
1294
+ syncRemoteFleetCss3dResizeSurface(nodeEntry, { render: false });
1235
1295
  }
1236
1296
 
1237
1297
  if (window.MindMapCss3DManager?.syncAgentPlanStack) {
@@ -1807,12 +1867,13 @@
1807
1867
  // ▲▲▲ [Fix] ▲▲▲
1808
1868
  }
1809
1869
 
1810
- // userData 업데이트
1811
- nodeEntry.cssObject.userData.worldWidth = nodeEntry.model.width;
1812
- nodeEntry.cssObject.userData.worldHeight = nodeEntry.model.height;
1813
- }
1814
- // ▲▲▲ [Fix] ▲▲▲
1815
- }
1870
+ // userData 업데이트
1871
+ nodeEntry.cssObject.userData.worldWidth = nodeEntry.model.width;
1872
+ nodeEntry.cssObject.userData.worldHeight = nodeEntry.model.height;
1873
+ syncRemoteFleetCss3dResizeSurface(nodeEntry, { render: true });
1874
+ }
1875
+ // ▲▲▲ [Fix] ▲▲▲
1876
+ }
1816
1877
  try {
1817
1878
  await module.dotNetHelper.invokeMethodAsync(
1818
1879
  'UpdateNodeDimensions',
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "mainAssemblyName": "MindExecution.Web",
3
3
  "resources": {
4
- "hash": "sha256-JCbjf1qv2j0vJHNTnD3Q1ATe3UeA0KwnDkNIU4CEVMw=",
4
+ "hash": "sha256-VbzQ9FDVKv1k9HSQjBpufXXSFyypvSzDv6diX7R22Pw=",
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.n5peonkatw.dll": "MindExecution.Kernel.dll",
128
128
  "MindExecution.Plugins.Admin.5zyeb2m709.dll": "MindExecution.Plugins.Admin.dll",
129
129
  "MindExecution.Plugins.Business.jn5nc7okql.dll": "MindExecution.Plugins.Business.dll",
130
- "MindExecution.Plugins.Concept.j3ndei56k5.dll": "MindExecution.Plugins.Concept.dll",
130
+ "MindExecution.Plugins.Concept.9wkocp9mtr.dll": "MindExecution.Plugins.Concept.dll",
131
131
  "MindExecution.Plugins.Directory.1argo44nph.dll": "MindExecution.Plugins.Directory.dll",
132
- "MindExecution.Plugins.PlanMaster.jx5e69sim0.dll": "MindExecution.Plugins.PlanMaster.dll",
133
- "MindExecution.Plugins.YouTube.qqwd3lc6cn.dll": "MindExecution.Plugins.YouTube.dll",
134
- "MindExecution.Shared.yykm4v7xnd.dll": "MindExecution.Shared.dll",
135
- "MindExecution.Web.2fexfu7nw7.dll": "MindExecution.Web.dll",
132
+ "MindExecution.Plugins.PlanMaster.esbz48id1o.dll": "MindExecution.Plugins.PlanMaster.dll",
133
+ "MindExecution.Plugins.YouTube.84y9bi1gi2.dll": "MindExecution.Plugins.YouTube.dll",
134
+ "MindExecution.Shared.epgga7dnyq.dll": "MindExecution.Shared.dll",
135
+ "MindExecution.Web.33jjm5osx9.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.te2oaei5ec.dll": "sha256-yzvF/UwfBMiJb2zQvlW0HSNU9VJeFPsgsB40BszINvc=",
282
282
  "MindExecution.Kernel.n5peonkatw.dll": "sha256-JfXgzqcnjRbW+XlMja53/jDG+/10sNVp+2V4F8w9s+Q=",
283
- "MindExecution.Plugins.Concept.j3ndei56k5.dll": "sha256-L9w4s1zohbMSXnxqVDSFbw4Qn7iQV2lbdyZKl98VfY4=",
284
- "MindExecution.Plugins.PlanMaster.jx5e69sim0.dll": "sha256-eSAg9lp6byLi2+lDlB5TIdRBpVS1viOfP6Ys+VCyMV0=",
285
- "MindExecution.Shared.yykm4v7xnd.dll": "sha256-qiMr2daTqpEJJr/fNvc1C7KwXWb9oHKQgLoA7RcGcp8=",
286
- "MindExecution.Web.2fexfu7nw7.dll": "sha256-Pp5EqyCnx8IBcVjF/cD8zXDo6i7zC8AQQtxz5qXyGxM="
283
+ "MindExecution.Plugins.Concept.9wkocp9mtr.dll": "sha256-yR8J6X8EHVEsX8HoKv4qEiXDb2svFAgOHpRUHysPW3k=",
284
+ "MindExecution.Plugins.PlanMaster.esbz48id1o.dll": "sha256-birepmbiBhlyA+hKwmofYfcG/PQzltuAi/ArgJITews=",
285
+ "MindExecution.Shared.epgga7dnyq.dll": "sha256-bvGDhZ63Omm5J7Wi24jWJrR9BfXgAC4kOGdfu8Oo2xM=",
286
+ "MindExecution.Web.33jjm5osx9.dll": "sha256-oY6r6MMAQn+tTAjj3OBUfb5vFTu8/ARH0tGsxDHzf9Y="
287
287
  },
288
288
  "lazyAssembly": {
289
289
  "MindExecution.Plugins.Admin.5zyeb2m709.dll": "sha256-kfvMS18tjQsoBT/nL40x6HiLaNM3Ls5G71Fk4skXtLg=",
290
290
  "MindExecution.Plugins.Business.jn5nc7okql.dll": "sha256-XwSTzDqTVFI7Ok/VMeaIQW/zbIp0Lx7dvWJ8QC7K3w8=",
291
291
  "MindExecution.Plugins.Directory.1argo44nph.dll": "sha256-GZZuAT3WZd9wDjQd+H8f6V9R2UYeLl/VOZxl9BnQVO0=",
292
- "MindExecution.Plugins.YouTube.qqwd3lc6cn.dll": "sha256-/oH3DKVYccnsdkwTAM//1MSyJQDCsbGWvYNkDRuzGM8="
292
+ "MindExecution.Plugins.YouTube.84y9bi1gi2.dll": "sha256-CGhi65JywxbQoa9uhGP+3/fLvOCrbEbGDea2P8M0m2M="
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=20260617-skill-ui-v600" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-skill-ui-v600" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260617-mdm-resize-reconnect-v601" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260617-mdm-resize-reconnect-v601" />
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-skill-ui-v600';
582
+ const scriptVersion = '20260617-mdm-resize-reconnect-v601';
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": "okvSWTbD",
2
+ "version": "+QtDGuJR",
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-Gq7oFLeDeJULsLOOgrIOKIoXGKmlPxoHcFqUJY1Cby8=",
89
+ "hash": "sha256-HUh8SFzEyHEcNhTeXl4RhIDL2N8FGgQ2loi+CMn8ZWk=",
90
90
  "url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
91
91
  },
92
92
  {
@@ -146,7 +146,7 @@
146
146
  "url": "_content/MindExecution.Shared/js/mind-map-object-manager.js.backup"
147
147
  },
148
148
  {
149
- "hash": "sha256-7gt5GUp6oiL+vW1pakGSnwgtljCyI3Qh96qAU0hV7Ak=",
149
+ "hash": "sha256-CbH7IH0gNoo/R/o1pBkuBcU753K+twxK2mCqkjO6zjI=",
150
150
  "url": "_content/MindExecution.Shared/js/mind-map-pipeline.js"
151
151
  },
152
152
  {
@@ -426,28 +426,28 @@
426
426
  "url": "_framework/MindExecution.Plugins.Business.jn5nc7okql.dll"
427
427
  },
428
428
  {
429
- "hash": "sha256-L9w4s1zohbMSXnxqVDSFbw4Qn7iQV2lbdyZKl98VfY4=",
430
- "url": "_framework/MindExecution.Plugins.Concept.j3ndei56k5.dll"
429
+ "hash": "sha256-yR8J6X8EHVEsX8HoKv4qEiXDb2svFAgOHpRUHysPW3k=",
430
+ "url": "_framework/MindExecution.Plugins.Concept.9wkocp9mtr.dll"
431
431
  },
432
432
  {
433
433
  "hash": "sha256-GZZuAT3WZd9wDjQd+H8f6V9R2UYeLl/VOZxl9BnQVO0=",
434
434
  "url": "_framework/MindExecution.Plugins.Directory.1argo44nph.dll"
435
435
  },
436
436
  {
437
- "hash": "sha256-eSAg9lp6byLi2+lDlB5TIdRBpVS1viOfP6Ys+VCyMV0=",
438
- "url": "_framework/MindExecution.Plugins.PlanMaster.jx5e69sim0.dll"
437
+ "hash": "sha256-birepmbiBhlyA+hKwmofYfcG/PQzltuAi/ArgJITews=",
438
+ "url": "_framework/MindExecution.Plugins.PlanMaster.esbz48id1o.dll"
439
439
  },
440
440
  {
441
- "hash": "sha256-/oH3DKVYccnsdkwTAM//1MSyJQDCsbGWvYNkDRuzGM8=",
442
- "url": "_framework/MindExecution.Plugins.YouTube.qqwd3lc6cn.dll"
441
+ "hash": "sha256-CGhi65JywxbQoa9uhGP+3/fLvOCrbEbGDea2P8M0m2M=",
442
+ "url": "_framework/MindExecution.Plugins.YouTube.84y9bi1gi2.dll"
443
443
  },
444
444
  {
445
- "hash": "sha256-qiMr2daTqpEJJr/fNvc1C7KwXWb9oHKQgLoA7RcGcp8=",
446
- "url": "_framework/MindExecution.Shared.yykm4v7xnd.dll"
445
+ "hash": "sha256-bvGDhZ63Omm5J7Wi24jWJrR9BfXgAC4kOGdfu8Oo2xM=",
446
+ "url": "_framework/MindExecution.Shared.epgga7dnyq.dll"
447
447
  },
448
448
  {
449
- "hash": "sha256-Pp5EqyCnx8IBcVjF/cD8zXDo6i7zC8AQQtxz5qXyGxM=",
450
- "url": "_framework/MindExecution.Web.2fexfu7nw7.dll"
449
+ "hash": "sha256-oY6r6MMAQn+tTAjj3OBUfb5vFTu8/ARH0tGsxDHzf9Y=",
450
+ "url": "_framework/MindExecution.Web.33jjm5osx9.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-QrUEaGJQOd/YpbUcxCpBv1/IaYxpxpfQqrZilgripfg=",
773
+ "hash": "sha256-VDxne0z23poLPLBSJ7cGId3lvBOoMAeHimT6xgr+Gqw=",
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-EII4T7BxjdPyROthZ8D8WjVz+5i2y1dcsUP6JehP0sI=",
837
+ "hash": "sha256-Qf6M96T+/y2AJeF+gEWuIhhNYDBYOFI/M7pLU8fiUfM=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: okvSWTbD */
1
+ /* Manifest version: +QtDGuJR */
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