@mindexec/cli 0.2.56 → 0.2.57

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.56",
3
+ "version": "0.2.57",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -742,9 +742,11 @@ try {
742
742
  receivedAt: new Date().toISOString()
743
743
  }]);
744
744
  assert.equal(patchCount, 1);
745
+ await wait();
745
746
  assert.equal(patchPreview.dataset.remoteFleetFrameSeq, '9999');
746
747
  assert.equal(patchPreview.dataset.remoteFleetFrameUrl, patchUrl);
747
748
  assert.equal(patchPreview.dataset.remoteFleetPendingFrameUrl || '', '');
749
+ assert.ok(patchPreview.querySelector('canvas[data-remote-fleet-frame-canvas="true"]'));
748
750
  assert.equal(patchPreview.querySelector('img[data-remote-fleet-frame-image="true"]')?.dataset.remoteFleetFrameUrl, patchUrl);
749
751
  const alternateDevice = devices.find(device => device.DeviceId !== focusedDevice.DeviceId);
750
752
  assert.ok(alternateDevice);
@@ -12840,6 +12840,7 @@
12840
12840
  const REMOTE_FLEET_LIVE_REFRESH_MS = 5000;
12841
12841
  const REMOTE_FLEET_LIVE_FRAME_REFRESH_MS = 50;
12842
12842
  const REMOTE_FLEET_THUMBNAIL_FRAME_REFRESH_MS = 2000;
12843
+ const REMOTE_FLEET_FRAME_CANVAS_MAX_DPR = 2;
12843
12844
  const REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS = 250;
12844
12845
  const REMOTE_FLEET_TASK_FOLLOW_REFRESH_MS = 2000;
12845
12846
  const REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS = 60;
@@ -13172,6 +13173,125 @@
13172
13173
  return image;
13173
13174
  }
13174
13175
 
13176
+ function ensureRemoteFleetFrameCanvas(preview) {
13177
+ let canvas = preview?.querySelector?.('canvas[data-remote-fleet-frame-canvas="true"]');
13178
+ if (canvas) {
13179
+ return canvas;
13180
+ }
13181
+
13182
+ canvas = document.createElement('canvas');
13183
+ canvas.dataset.remoteFleetFrameCanvas = 'true';
13184
+ canvas.setAttribute('aria-hidden', 'true');
13185
+ canvas.style.cssText = `
13186
+ position: absolute;
13187
+ inset: 0;
13188
+ width: 100%;
13189
+ height: 100%;
13190
+ display: none;
13191
+ background: #0f172a;
13192
+ `;
13193
+ if (typeof preview?.insertBefore === 'function') {
13194
+ preview.insertBefore(canvas, preview.firstChild || null);
13195
+ } else {
13196
+ preview?.appendChild?.(canvas);
13197
+ }
13198
+ return canvas;
13199
+ }
13200
+
13201
+ function syncRemoteFleetFrameCanvasSize(canvas) {
13202
+ if (!canvas) {
13203
+ return null;
13204
+ }
13205
+
13206
+ const rect = typeof canvas.getBoundingClientRect === 'function'
13207
+ ? canvas.getBoundingClientRect()
13208
+ : null;
13209
+ const cssWidth = Math.max(1, Math.round(rect?.width || canvas.clientWidth || 320));
13210
+ const cssHeight = Math.max(1, Math.round(rect?.height || canvas.clientHeight || 180));
13211
+ const dpr = Math.max(1, Math.min(REMOTE_FLEET_FRAME_CANVAS_MAX_DPR, Number(window.devicePixelRatio || 1) || 1));
13212
+ const nextWidth = Math.max(1, Math.round(cssWidth * dpr));
13213
+ const nextHeight = Math.max(1, Math.round(cssHeight * dpr));
13214
+ if (canvas.width !== nextWidth) {
13215
+ canvas.width = nextWidth;
13216
+ }
13217
+ if (canvas.height !== nextHeight) {
13218
+ canvas.height = nextHeight;
13219
+ }
13220
+ return { width: nextWidth, height: nextHeight };
13221
+ }
13222
+
13223
+ function getRemoteFleetBitmapSize(bitmap) {
13224
+ const width = Number(bitmap?.displayWidth || bitmap?.naturalWidth || bitmap?.videoWidth || bitmap?.width || 0);
13225
+ const height = Number(bitmap?.displayHeight || bitmap?.naturalHeight || bitmap?.videoHeight || bitmap?.height || 0);
13226
+ return {
13227
+ width: Number.isFinite(width) && width > 0 ? width : 1,
13228
+ height: Number.isFinite(height) && height > 0 ? height : 1
13229
+ };
13230
+ }
13231
+
13232
+ function drawRemoteFleetFrameToCanvas(canvas, bitmap) {
13233
+ if (!canvas || !bitmap) {
13234
+ return false;
13235
+ }
13236
+
13237
+ const size = syncRemoteFleetFrameCanvasSize(canvas);
13238
+ if (!size) {
13239
+ return false;
13240
+ }
13241
+
13242
+ let context = null;
13243
+ try {
13244
+ context = canvas.getContext('2d', { alpha: false, desynchronized: true });
13245
+ } catch {
13246
+ context = canvas.getContext('2d');
13247
+ }
13248
+ if (!context) {
13249
+ return false;
13250
+ }
13251
+
13252
+ const source = getRemoteFleetBitmapSize(bitmap);
13253
+ const sourceAspect = source.width / source.height;
13254
+ const targetAspect = size.width / size.height;
13255
+ let sx = 0;
13256
+ let sy = 0;
13257
+ let sw = source.width;
13258
+ let sh = source.height;
13259
+ if (sourceAspect > targetAspect) {
13260
+ sw = source.height * targetAspect;
13261
+ sx = (source.width - sw) / 2;
13262
+ } else if (sourceAspect < targetAspect) {
13263
+ sh = source.width / targetAspect;
13264
+ sy = (source.height - sh) / 2;
13265
+ }
13266
+
13267
+ context.imageSmoothingEnabled = true;
13268
+ context.imageSmoothingQuality = 'medium';
13269
+ context.clearRect(0, 0, size.width, size.height);
13270
+ context.drawImage(bitmap, sx, sy, sw, sh, 0, 0, size.width, size.height);
13271
+ return true;
13272
+ }
13273
+
13274
+ async function loadRemoteFleetFrameBitmap(frame) {
13275
+ if (!frame || !isRemoteFleetFrameSource(frame.frameUrl)) {
13276
+ return null;
13277
+ }
13278
+
13279
+ if (typeof fetch !== 'function' || typeof createImageBitmap !== 'function') {
13280
+ return null;
13281
+ }
13282
+
13283
+ const response = await fetch(frame.frameUrl, {
13284
+ cache: 'no-store',
13285
+ credentials: 'omit'
13286
+ });
13287
+ if (!response.ok) {
13288
+ throw new Error(`remote-frame-fetch-${response.status}`);
13289
+ }
13290
+
13291
+ const blob = await response.blob();
13292
+ return createImageBitmap(blob);
13293
+ }
13294
+
13175
13295
  function getRemoteFleetFrameIdentity(frame) {
13176
13296
  return [
13177
13297
  String(frame?.deviceId || '').trim(),
@@ -13272,20 +13392,12 @@
13272
13392
  return badge;
13273
13393
  }
13274
13394
 
13275
- function commitRemoteFleetFrameToPreview(preview, image, frame) {
13276
- if (!preview || !image || !isRemoteFleetFrameNewerForPreview(preview, frame, false)) {
13395
+ function commitRemoteFleetFrameMetadata(preview, frame) {
13396
+ if (!preview || !isRemoteFleetFrameNewerForPreview(preview, frame, false)) {
13277
13397
  return false;
13278
13398
  }
13279
13399
 
13280
13400
  const nextSeq = Number(frame.frameSeq || 0);
13281
- image.dataset.remoteFleetFrameKind = frame.kind;
13282
- image.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13283
- image.dataset.remoteFleetFrameUrl = frame.frameUrl;
13284
- image.loading = frame.kind === 'thumbnail' ? 'lazy' : 'eager';
13285
- if (image.src !== frame.frameUrl) {
13286
- image.src = frame.frameUrl;
13287
- }
13288
-
13289
13401
  preview.dataset.remoteFleetFrameKind = frame.kind;
13290
13402
  preview.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13291
13403
  preview.dataset.remoteFleetFrameUrl = frame.frameUrl;
@@ -13311,6 +13423,50 @@
13311
13423
  return true;
13312
13424
  }
13313
13425
 
13426
+ function commitRemoteFleetFrameToPreview(preview, image, frame) {
13427
+ if (!preview || !image || !isRemoteFleetFrameNewerForPreview(preview, frame, false)) {
13428
+ return false;
13429
+ }
13430
+
13431
+ const nextSeq = Number(frame.frameSeq || 0);
13432
+ image.dataset.remoteFleetFrameKind = frame.kind;
13433
+ image.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13434
+ image.dataset.remoteFleetFrameUrl = frame.frameUrl;
13435
+ image.loading = frame.kind === 'thumbnail' ? 'lazy' : 'eager';
13436
+ image.style.display = 'block';
13437
+ if (image.src !== frame.frameUrl) {
13438
+ image.src = frame.frameUrl;
13439
+ }
13440
+
13441
+ const canvas = preview.querySelector?.('canvas[data-remote-fleet-frame-canvas="true"]');
13442
+ if (canvas) {
13443
+ canvas.style.display = 'none';
13444
+ }
13445
+
13446
+ return commitRemoteFleetFrameMetadata(preview, frame);
13447
+ }
13448
+
13449
+ function commitRemoteFleetFrameToCanvas(preview, canvas, image, bitmap, frame) {
13450
+ if (!preview || !canvas || !bitmap || !isRemoteFleetFrameNewerForPreview(preview, frame, false)) {
13451
+ return false;
13452
+ }
13453
+
13454
+ if (!drawRemoteFleetFrameToCanvas(canvas, bitmap)) {
13455
+ return false;
13456
+ }
13457
+
13458
+ const nextSeq = Number(frame.frameSeq || 0);
13459
+ canvas.dataset.remoteFleetFrameKind = frame.kind;
13460
+ canvas.dataset.remoteFleetFrameSeq = String(nextSeq || 0);
13461
+ canvas.dataset.remoteFleetFrameUrl = frame.frameUrl;
13462
+ canvas.style.display = 'block';
13463
+ if (image) {
13464
+ image.style.display = 'none';
13465
+ }
13466
+
13467
+ return commitRemoteFleetFrameMetadata(preview, frame);
13468
+ }
13469
+
13314
13470
  function clearRemoteFleetPendingFrameDataset(preview, frame) {
13315
13471
  if (!preview) {
13316
13472
  return;
@@ -13325,7 +13481,7 @@
13325
13481
  }
13326
13482
  }
13327
13483
 
13328
- function processRemoteFleetFrameQueue(preview, image) {
13484
+ function processRemoteFleetFramePaintQueue(preview, image) {
13329
13485
  if (!preview || !image || preview._remoteFleetFrameLoaderActive === true) {
13330
13486
  return;
13331
13487
  }
@@ -13338,7 +13494,7 @@
13338
13494
 
13339
13495
  preview._remoteFleetFrameLoaderActive = true;
13340
13496
  const frameIdentity = getRemoteFleetFrameIdentity(frame);
13341
- const finish = loaded => {
13497
+ const finish = (loaded, surface = 'img') => {
13342
13498
  const currentPending = preview._remoteFleetPendingFrame;
13343
13499
  const stillLatest = getRemoteFleetFrameIdentity(currentPending) === frameIdentity;
13344
13500
  let committed = false;
@@ -13347,7 +13503,8 @@
13347
13503
  window.RuntimeTrace?.emit?.('remote.frame.uiPatched', {
13348
13504
  count: committed ? 1 : 0,
13349
13505
  kind: frame.kind,
13350
- seq: frame.frameSeq
13506
+ seq: frame.frameSeq,
13507
+ surface
13351
13508
  });
13352
13509
  }
13353
13510
 
@@ -13357,28 +13514,84 @@
13357
13514
 
13358
13515
  preview._remoteFleetFrameLoaderActive = false;
13359
13516
  if (preview._remoteFleetPendingFrame) {
13360
- processRemoteFleetFrameQueue(preview, image);
13517
+ processRemoteFleetFramePaintQueue(preview, image);
13518
+ }
13519
+ };
13520
+
13521
+ const loadFallbackImage = () => {
13522
+ if (typeof Image !== 'function') {
13523
+ finish(true, 'img');
13524
+ return;
13361
13525
  }
13526
+
13527
+ const loader = new Image();
13528
+ loader.decoding = 'async';
13529
+ loader.onload = () => {
13530
+ const decoded = typeof loader.decode === 'function'
13531
+ ? loader.decode().catch(() => undefined)
13532
+ : Promise.resolve();
13533
+ decoded.then(() => finish(true, 'img'));
13534
+ };
13535
+ loader.onerror = () => finish(false, 'img');
13536
+ loader.src = frame.frameUrl;
13362
13537
  };
13363
13538
 
13364
- if (typeof Image !== 'function') {
13365
- finish(true);
13539
+ const canvas = ensureRemoteFleetFrameCanvas(preview);
13540
+ if (!canvas) {
13541
+ loadFallbackImage();
13366
13542
  return;
13367
13543
  }
13368
13544
 
13369
- const loader = new Image();
13370
- loader.decoding = 'async';
13371
- loader.onload = () => {
13372
- const decoded = typeof loader.decode === 'function'
13373
- ? loader.decode().catch(() => undefined)
13374
- : Promise.resolve();
13375
- decoded.then(() => finish(true));
13376
- };
13377
- loader.onerror = () => finish(false);
13378
- loader.src = frame.frameUrl;
13545
+ loadRemoteFleetFrameBitmap(frame)
13546
+ .then(bitmap => {
13547
+ if (!bitmap) {
13548
+ loadFallbackImage();
13549
+ return;
13550
+ }
13551
+
13552
+ requestRemoteFleetFrameLoopFrame(() => {
13553
+ if (!document.body.contains(preview)) {
13554
+ if (typeof bitmap.close === 'function') {
13555
+ bitmap.close();
13556
+ }
13557
+ finish(false, 'canvas');
13558
+ return;
13559
+ }
13560
+
13561
+ const currentPending = preview._remoteFleetPendingFrame;
13562
+ const stillLatest = getRemoteFleetFrameIdentity(currentPending) === frameIdentity;
13563
+ const committed = stillLatest
13564
+ ? commitRemoteFleetFrameToCanvas(preview, canvas, image, bitmap, frame)
13565
+ : false;
13566
+ if (typeof bitmap.close === 'function') {
13567
+ bitmap.close();
13568
+ }
13569
+
13570
+ if (committed) {
13571
+ window.RuntimeTrace?.emit?.('remote.frame.uiPatched', {
13572
+ count: 1,
13573
+ kind: frame.kind,
13574
+ seq: frame.frameSeq,
13575
+ surface: 'canvas'
13576
+ });
13577
+ if (stillLatest) {
13578
+ clearRemoteFleetPendingFrameDataset(preview, frame);
13579
+ }
13580
+ preview._remoteFleetFrameLoaderActive = false;
13581
+ if (preview._remoteFleetPendingFrame) {
13582
+ processRemoteFleetFramePaintQueue(preview, image);
13583
+ }
13584
+ } else if (stillLatest) {
13585
+ loadFallbackImage();
13586
+ } else {
13587
+ finish(false, 'canvas');
13588
+ }
13589
+ });
13590
+ })
13591
+ .catch(() => loadFallbackImage());
13379
13592
  }
13380
13593
 
13381
- function queueRemoteFleetFrameImageSwap(preview, frame) {
13594
+ function queueRemoteFleetFramePaint(preview, frame) {
13382
13595
  if (!preview || !frame || !isRemoteFleetFrameNewerForPreview(preview, frame, true)) {
13383
13596
  return false;
13384
13597
  }
@@ -13393,12 +13606,12 @@
13393
13606
  preview.dataset.remoteFleetPendingFrameKind = nextFrame.kind;
13394
13607
  preview.dataset.remoteFleetPendingFrameSeq = String(nextFrame.frameSeq || 0);
13395
13608
  preview.dataset.remoteFleetPendingFrameUrl = nextFrame.frameUrl;
13396
- processRemoteFleetFrameQueue(preview, image);
13609
+ processRemoteFleetFramePaintQueue(preview, image);
13397
13610
  return true;
13398
13611
  }
13399
13612
 
13400
13613
  function applyRemoteFleetFramePatchToPreview(preview, frame) {
13401
- return queueRemoteFleetFrameImageSwap(preview, frame);
13614
+ return queueRemoteFleetFramePaint(preview, frame);
13402
13615
  }
13403
13616
 
13404
13617
  function applyRemoteFleetFramePatches(bodyView, patches) {
@@ -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=20260614-remote-registry-wake-v516" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260614-remote-registry-wake-v516" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260614-remote-canvas-frame-painter-v517" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260614-remote-canvas-frame-painter-v517" />
12
12
  <!-- ?쇄뼹??Font Awesome (local) ?쇄뼹??-->
13
13
  <link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
14
14
  <!-- ?꿎뼯??-->
@@ -558,7 +558,7 @@
558
558
  }
559
559
 
560
560
  const base = '_content/MindExecution.Shared/js/';
561
- const scriptVersion = '20260614-remote-registry-wake-v516';
561
+ const scriptVersion = '20260614-remote-canvas-frame-painter-v517';
562
562
  const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
563
563
  console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
564
564
  const criticalScripts = [
@@ -1,5 +1,5 @@
1
1
  self.assetsManifest = {
2
- "version": "myLeiE66",
2
+ "version": "KpaZ4pzK",
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-pfqJn3HbG2hf6mQB5J36TJM5Ko6Jj7R0B7EqxBnfo20=",
89
+ "hash": "sha256-x4uXuDyBscw/I1YWnNTwWzM4+1PkYmbxtXau4hRBGlI=",
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-0isEjWtcxpTZnvY3qV3eTiWX+iwsmslA96igYDcNwB4=",
837
+ "hash": "sha256-ve5/RFGEOkIRyDqWQLvQA728TLeR5I6XaPPAS2HsVsQ=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: myLeiE66 */
1
+ /* Manifest version: KpaZ4pzK */
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