@mindexec/cli 0.2.19 → 0.2.20

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.19",
3
+ "version": "0.2.20",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -652,6 +652,10 @@ try {
652
652
  assert.ok(resultPanel.textContent.includes('synthetic-render-ai'));
653
653
  assert.ok(resultPanel.textContent.includes('Overview AI result visible'));
654
654
  assert.ok(devices.some(device => /^synthetic-response-/.test(device.LatestTaskResultResponseId)));
655
+ await wait(320);
656
+ assert.ok(dotNetCalls.some(call => call.methodName === 'RefreshRemoteFleetMonitorNodeFromJs'));
657
+ assert.equal(bodyView.dataset.remoteFleetTaskFollowKey, 'render-smoke-batch');
658
+ assert.ok(Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0') >= 1);
655
659
 
656
660
  const searchInput = bodyView.querySelector('[data-remote-fleet-search="true"]');
657
661
  searchInput.value = 'synthetic pc 0001';
@@ -12005,6 +12005,73 @@
12005
12005
  }
12006
12006
  }
12007
12007
 
12008
+ function getRemoteFleetTaskBatchValue(batch, camelKey, pascalKey, fallback = '') {
12009
+ const value = batch?.[camelKey] ?? batch?.[pascalKey] ?? fallback;
12010
+ return value === undefined || value === null ? fallback : value;
12011
+ }
12012
+
12013
+ function getRemoteFleetTaskBatchNumber(batch, camelKey, pascalKey) {
12014
+ const value = Number(getRemoteFleetTaskBatchValue(batch, camelKey, pascalKey, 0));
12015
+ return Number.isFinite(value) ? value : 0;
12016
+ }
12017
+
12018
+ function getRemoteFleetTaskBatchKey(batch) {
12019
+ if (!batch || typeof batch !== 'object') {
12020
+ return '';
12021
+ }
12022
+
12023
+ const batchId = String(getRemoteFleetTaskBatchValue(batch, 'batchId', 'BatchId', '')).trim();
12024
+ if (batchId) {
12025
+ return batchId;
12026
+ }
12027
+
12028
+ const requestedAt = String(getRemoteFleetTaskBatchValue(batch, 'requestedAt', 'RequestedAt', '')).trim();
12029
+ const updatedAt = String(getRemoteFleetTaskBatchValue(batch, 'updatedAt', 'UpdatedAt', '')).trim();
12030
+ const title = String(getRemoteFleetTaskBatchValue(batch, 'title', 'Title', '')).trim();
12031
+ const total = getRemoteFleetTaskBatchNumber(batch, 'total', 'Total');
12032
+ return [title, requestedAt, updatedAt, total].filter(Boolean).join(':');
12033
+ }
12034
+
12035
+ function isRemoteFleetTaskBatchActive(batch) {
12036
+ if (!batch || typeof batch !== 'object') {
12037
+ return false;
12038
+ }
12039
+
12040
+ const status = String(getRemoteFleetTaskBatchValue(batch, 'status', 'Status', '')).trim().toLowerCase();
12041
+ const pending = getRemoteFleetTaskBatchNumber(batch, 'pending', 'Pending');
12042
+ const total = getRemoteFleetTaskBatchNumber(batch, 'total', 'Total');
12043
+ const completed = getRemoteFleetTaskBatchNumber(batch, 'completed', 'Completed');
12044
+ const failed = getRemoteFleetTaskBatchNumber(batch, 'failed', 'Failed');
12045
+ const terminalStatuses = new Set(['completed', 'completed-with-failures', 'failed', 'cancelled', 'canceled', 'done']);
12046
+ if (terminalStatuses.has(status)) {
12047
+ return false;
12048
+ }
12049
+
12050
+ if (pending > 0) {
12051
+ return true;
12052
+ }
12053
+
12054
+ if (['running', 'queued', 'pending', 'targeted', 'dispatching', 'in-progress'].includes(status)) {
12055
+ return true;
12056
+ }
12057
+
12058
+ return total > 0 && completed + failed < total;
12059
+ }
12060
+
12061
+ function getRemoteFleetTaskBatchFromResult(result) {
12062
+ const direct = result?.batch
12063
+ ?? result?.Batch
12064
+ ?? result?.taskBatch
12065
+ ?? result?.TaskBatch
12066
+ ?? result?.latestTaskBatch
12067
+ ?? result?.LatestTaskBatch
12068
+ ?? result?.refresh?.batch
12069
+ ?? result?.refresh?.Batch;
12070
+ return direct && typeof direct === 'object' && !Array.isArray(direct)
12071
+ ? direct
12072
+ : null;
12073
+ }
12074
+
12008
12075
  function parseRemoteFleetPinnedDevice(nodeModel) {
12009
12076
  const raw = getRemoteFleetMetadataValue(nodeModel, 'RemoteFleetPinnedDeviceJson', '{}');
12010
12077
  if (!raw.trim()) {
@@ -12174,6 +12241,9 @@
12174
12241
 
12175
12242
  const REMOTE_FLEET_MONITOR_REFRESH_MS = 5000;
12176
12243
  const REMOTE_FLEET_LIVE_REFRESH_MS = 1000;
12244
+ const REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS = 250;
12245
+ const REMOTE_FLEET_TASK_FOLLOW_REFRESH_MS = 2000;
12246
+ const REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS = 60;
12177
12247
 
12178
12248
  function clearRemoteFleetTimers(bodyView) {
12179
12249
  if (!bodyView) return;
@@ -12185,6 +12255,10 @@
12185
12255
  clearInterval(bodyView._remoteFleetMonitorRefreshTimer);
12186
12256
  bodyView._remoteFleetMonitorRefreshTimer = null;
12187
12257
  }
12258
+ if (bodyView._remoteFleetTaskFollowTimer) {
12259
+ clearTimeout(bodyView._remoteFleetTaskFollowTimer);
12260
+ bodyView._remoteFleetTaskFollowTimer = null;
12261
+ }
12188
12262
  }
12189
12263
 
12190
12264
  function getRemoteFleetDeviceField(device, camelKey, pascalKey, fallback = '') {
@@ -12900,6 +12974,13 @@
12900
12974
  const focusState = bodyView.dataset.remoteFleetFocusDeviceId || '';
12901
12975
  const latestTaskBatch = parseRemoteFleetLatestTaskBatch(nodeModel);
12902
12976
  const recentTaskBatches = parseRemoteFleetRecentTaskBatches(nodeModel);
12977
+ const latestTaskBatchKey = getRemoteFleetTaskBatchKey(latestTaskBatch);
12978
+ const latestTaskBatchActive = isRemoteFleetTaskBatchActive(latestTaskBatch);
12979
+ if (latestTaskBatchKey && bodyView.dataset.remoteFleetTaskFollowKey !== latestTaskBatchKey) {
12980
+ bodyView.dataset.remoteFleetTaskFollowKey = latestTaskBatchKey;
12981
+ bodyView.dataset.remoteFleetTaskFollowTicks = '0';
12982
+ }
12983
+ bodyView.dataset.remoteFleetTaskFollowActive = latestTaskBatchActive ? 'true' : 'false';
12903
12984
  const sortedDevices = [...parseRemoteFleetDevices(nodeModel)]
12904
12985
  .sort((left, right) => compareRemoteFleetDevices(left, right, sortState));
12905
12986
  const devices = groupState === 'none'
@@ -14035,6 +14116,84 @@
14035
14116
  bodyView._remoteFleetRefreshInFlight = false;
14036
14117
  }
14037
14118
  };
14119
+ const prepareRemoteFleetTaskFollow = batch => {
14120
+ if (!isRemoteFleetTaskBatchActive(batch)) {
14121
+ bodyView.dataset.remoteFleetTaskFollowActive = 'false';
14122
+ return false;
14123
+ }
14124
+
14125
+ const batchKey = getRemoteFleetTaskBatchKey(batch);
14126
+ if (batchKey && bodyView.dataset.remoteFleetTaskFollowKey !== batchKey) {
14127
+ bodyView.dataset.remoteFleetTaskFollowKey = batchKey;
14128
+ bodyView.dataset.remoteFleetTaskFollowTicks = '0';
14129
+ }
14130
+
14131
+ bodyView.dataset.remoteFleetTaskFollowActive = 'true';
14132
+ return true;
14133
+ };
14134
+ const scheduleRemoteFleetTaskFollow = (delayMs = REMOTE_FLEET_TASK_FOLLOW_INITIAL_MS) => {
14135
+ if (bodyView._remoteFleetTaskFollowTimer) {
14136
+ clearTimeout(bodyView._remoteFleetTaskFollowTimer);
14137
+ bodyView._remoteFleetTaskFollowTimer = null;
14138
+ }
14139
+
14140
+ if (bodyView.dataset.remoteFleetTaskFollowActive !== 'true') {
14141
+ return;
14142
+ }
14143
+
14144
+ const ticks = Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0');
14145
+ if (Number.isFinite(ticks) && ticks >= REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS) {
14146
+ bodyView.dataset.remoteFleetTaskFollowActive = 'false';
14147
+ window.RuntimeTrace?.emit?.('remote.task.followStopped', {
14148
+ nodeId,
14149
+ batchKey: bodyView.dataset.remoteFleetTaskFollowKey || '',
14150
+ reason: 'max-ticks'
14151
+ });
14152
+ return;
14153
+ }
14154
+
14155
+ const timer = setTimeout(async () => {
14156
+ bodyView._remoteFleetTaskFollowTimer = null;
14157
+ if (!document.body.contains(bodyView)) {
14158
+ clearRemoteFleetTimers(bodyView);
14159
+ return;
14160
+ }
14161
+
14162
+ const currentTicks = Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0');
14163
+ bodyView.dataset.remoteFleetTaskFollowTicks = String((Number.isFinite(currentTicks) ? currentTicks : 0) + 1);
14164
+ window.RuntimeTrace?.emit?.('remote.task.followRefresh', {
14165
+ nodeId,
14166
+ batchKey: bodyView.dataset.remoteFleetTaskFollowKey || '',
14167
+ tick: Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0')
14168
+ });
14169
+
14170
+ try {
14171
+ await refreshRemoteFleetNode();
14172
+ } catch {
14173
+ clearRemoteFleetTimers(bodyView);
14174
+ return;
14175
+ }
14176
+
14177
+ if (!document.body.contains(bodyView)) {
14178
+ clearRemoteFleetTimers(bodyView);
14179
+ return;
14180
+ }
14181
+
14182
+ const nextTicks = Number(bodyView.dataset.remoteFleetTaskFollowTicks || '0');
14183
+ if (bodyView.dataset.remoteFleetTaskFollowActive === 'true'
14184
+ && (!Number.isFinite(nextTicks) || nextTicks < REMOTE_FLEET_TASK_FOLLOW_MAX_TICKS)) {
14185
+ scheduleRemoteFleetTaskFollow(REMOTE_FLEET_TASK_FOLLOW_REFRESH_MS);
14186
+ }
14187
+ }, Math.max(0, Number(delayMs) || 0));
14188
+ timer?.unref?.();
14189
+ bodyView._remoteFleetTaskFollowTimer = timer;
14190
+ };
14191
+ const startRemoteFleetTaskFollowFromResult = result => {
14192
+ const batch = getRemoteFleetTaskBatchFromResult(result) || latestTaskBatch;
14193
+ if (prepareRemoteFleetTaskFollow(batch)) {
14194
+ scheduleRemoteFleetTaskFollow();
14195
+ }
14196
+ };
14038
14197
  const getVisibleEligibleDeviceIds = () => {
14039
14198
  const wantsAi = useAiAssist();
14040
14199
  return getDeviceCards()
@@ -14150,6 +14309,9 @@
14150
14309
  renderRemoteFleetMonitor(bodyView, nodeModel);
14151
14310
  });
14152
14311
  applyRemoteFleetFilters();
14312
+ if (latestTaskBatchActive) {
14313
+ scheduleRemoteFleetTaskFollow();
14314
+ }
14153
14315
 
14154
14316
  sendVisibleButton.addEventListener('click', async event => {
14155
14317
  event.preventDefault();
@@ -14175,6 +14337,7 @@
14175
14337
  const mode = useAiAssist() ? 'visible AI task' : 'visible remote task';
14176
14338
  const feedback = formatRemoteFleetDispatchFeedback(result, targetIds.length, mode);
14177
14339
  setTaskFeedback(feedback.text, feedback.tone);
14340
+ startRemoteFleetTaskFollowFromResult(result);
14178
14341
  } finally {
14179
14342
  applyRemoteFleetFilters();
14180
14343
  }
@@ -14198,6 +14361,7 @@
14198
14361
  const mode = useAiAssist() ? 'AI task' : 'remote task';
14199
14362
  const feedback = formatRemoteFleetDispatchFeedback(result, result?.total || 0, mode);
14200
14363
  setTaskFeedback(feedback.text, feedback.tone);
14364
+ startRemoteFleetTaskFollowFromResult(result);
14201
14365
  } finally {
14202
14366
  applyRemoteFleetFilters();
14203
14367
  }
@@ -14321,6 +14485,7 @@
14321
14485
  await syncRemoteFleetNodeStateFromResult(result);
14322
14486
  if (result?.success) {
14323
14487
  setTaskFeedback(useAiAssist() ? 'Queued AI task.' : 'Queued remote task.', 'success');
14488
+ startRemoteFleetTaskFollowFromResult(result);
14324
14489
  } else {
14325
14490
  setTaskFeedback(result?.error || 'Task dispatch failed.', 'error');
14326
14491
  }
@@ -558,7 +558,7 @@
558
558
  }
559
559
 
560
560
  const base = '_content/MindExecution.Shared/js/';
561
- const scriptVersion = '20260612-remote-task-results-v477';
561
+ const scriptVersion = '20260612-remote-task-follow-v478';
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": "dMeuj/jH",
2
+ "version": "dr5Y7e+X",
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-XktC8d/MT50tOHPQODkji8pOIOfC9eaaACAGUJVxd3I=",
89
+ "hash": "sha256-r/rKyK7pwOufIiynKaiu7pt8CgoBdLd7u+FmbZHVbko=",
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-fxCftcGIM5m9govtiX7DVdEDfsIDikwU9HHnJ4KMvEc=",
837
+ "hash": "sha256-0dZRFimqvytlX0CmLM1UGW//sqP9ru7W0usTp/5Z570=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: dMeuj/jH */
1
+ /* Manifest version: dr5Y7e+X */
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