@mindexec/cli 0.2.457 → 0.2.458

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.
Files changed (20) hide show
  1. package/package.json +1 -1
  2. package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
  3. package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
  4. package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
  5. package/scripts/remote-fleet-render-smoke.mjs +29 -186
  6. package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +51 -346
  7. package/wwwroot/_framework/{MindExecution.Core.speado072l.dll → MindExecution.Core.2ch68iyy8o.dll} +0 -0
  8. package/wwwroot/_framework/{MindExecution.Kernel.mjy31ssdac.dll → MindExecution.Kernel.dh617xfv36.dll} +0 -0
  9. package/wwwroot/_framework/{MindExecution.Plugins.Admin.vbjjmdaao2.dll → MindExecution.Plugins.Admin.0sm50hbae9.dll} +0 -0
  10. package/wwwroot/_framework/{MindExecution.Plugins.Business.0cr5jc6wqe.dll → MindExecution.Plugins.Business.3wq01orrbu.dll} +0 -0
  11. package/wwwroot/_framework/{MindExecution.Plugins.Concept.m7p666e0jd.dll → MindExecution.Plugins.Concept.z8yl28fa2a.dll} +0 -0
  12. package/wwwroot/_framework/{MindExecution.Plugins.Directory.kmdtirnljl.dll → MindExecution.Plugins.Directory.m7murp5oes.dll} +0 -0
  13. package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.m1pfeozacj.dll → MindExecution.Plugins.PlanMaster.yuyrbpf0vh.dll} +0 -0
  14. package/wwwroot/_framework/{MindExecution.Plugins.YouTube.nvsc9q4s6b.dll → MindExecution.Plugins.YouTube.rwxvn00rm2.dll} +0 -0
  15. package/wwwroot/_framework/{MindExecution.Shared.9jaznballd.dll → MindExecution.Shared.r9k48iyijb.dll} +0 -0
  16. package/wwwroot/_framework/{MindExecution.Web.k5jxwawryl.dll → MindExecution.Web.742aribkxm.dll} +0 -0
  17. package/wwwroot/_framework/blazor.boot.json +21 -21
  18. package/wwwroot/index.html +722 -722
  19. package/wwwroot/service-worker-assets.js +24 -24
  20. package/wwwroot/service-worker.js +1 -1
@@ -1,9 +1,9 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="utf-8" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>MindExec | Business Execution OS for solo builders</title>
8
8
  <meta name="description" content="MindExec is an AI business execution OS for solo builders who want to turn notes, research, assets, and repeatable execution Skills into revenue-producing work." />
9
9
  <base href="/" />
@@ -13,733 +13,733 @@
13
13
  <link rel="manifest" href="manifest.webmanifest?v=20260728-app-icon-v1" />
14
14
  <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260629-ai-task-flow-v863" />
15
15
  <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260629-mdm-shadow-v856" />
16
- <!-- ??좎뜦堉??Font Awesome (local) ??좎뜦堉??-->
17
- <link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
18
- <!-- ??좎뜦堉??-->
19
- <style>
20
- #app {
21
- min-height: 100vh;
22
- }
23
-
24
- .app-static-fallback {
25
- width: min(960px, calc(100% - 32px));
26
- margin: 0 auto;
27
- padding: 56px 0 48px;
28
- color: #0f172a;
29
- line-height: 1.7;
30
- }
31
-
32
- .app-static-fallback__eyebrow {
33
- display: inline-flex;
34
- padding: 6px 10px;
35
- border-radius: 999px;
36
- background: rgba(255, 255, 255, 0.84);
37
- border: 1px solid rgba(148, 163, 184, 0.25);
38
- font-size: 12px;
39
- font-weight: 700;
40
- color: #334155;
41
- }
42
-
43
- .app-static-fallback h1 {
44
- margin: 16px 0 0;
45
- font-size: clamp(30px, 4vw, 48px);
46
- line-height: 1.05;
47
- font-weight: 800;
48
- }
49
-
50
- .app-static-fallback p {
51
- max-width: 760px;
52
- margin: 16px 0 0;
53
- color: #475569;
54
- }
55
-
56
- .app-static-fallback a {
57
- color: #0f172a;
58
- font-weight: 700;
59
- }
60
-
61
- #blazor-error-ui {
62
- display: none;
63
- }
64
-
65
- #blazor-error-ui.is-visible {
66
- position: fixed;
67
- right: 20px;
68
- bottom: 20px;
69
- z-index: 9999;
70
- display: flex;
71
- align-items: center;
72
- gap: 12px;
73
- max-width: 420px;
74
- padding: 14px 16px;
75
- border-radius: 14px;
76
- background: rgba(15, 23, 42, 0.96);
77
- color: #fff;
78
- box-shadow: 0 18px 48px rgba(15, 23, 42, 0.28);
79
- }
80
-
81
- .blazor-error-ui__message {
82
- flex: 1;
83
- font-size: 14px;
84
- line-height: 1.6;
85
- }
86
-
87
- #blazor-error-ui .reload,
88
- #blazor-error-ui .dismiss {
89
- color: #fff;
90
- font-size: 13px;
91
- font-weight: 700;
92
- text-decoration: none;
93
- cursor: pointer;
94
- }
95
- </style>
96
- </head>
97
-
98
- <body>
99
- <div id="app-container">
100
- <div id="app">
101
- <article class="app-static-fallback" id="app-static-fallback">
102
- <div class="app-static-fallback__eyebrow">MindExec</div>
103
- <h1>MindExec</h1>
104
- <p>Turn ideas into revenue execution. MindExec is a Business Execution OS that moves serious work into MindCanvas, where context, AI Tasks, execution Skills, media, and results stay connected.</p>
105
- <p><a href="/mindcanvas">Open MindCanvas</a> | <a href="/pricing">See pricing</a> | <a href="/tools">Browse free tools</a></p>
106
- <noscript>
107
- <p>JavaScript is required for the interactive tool experience.</p>
108
- </noscript>
109
- </article>
110
- </div>
111
- </div>
112
-
113
- <div id="three-js-container"
114
- style="display: none; position: fixed; top:0; left:0; width:100%; height:100%; z-index:999; background-color: rgba(0,0,0,0.5);">
115
- </div>
116
-
117
- <!-- Selection rectangle overlay -->
118
- <div id="selection-rectangle"
119
- style="position: fixed; border:2px solid #1173d4; background-color: rgba(17, 115, 212, 0.15); pointer-events: none; display: none; z-index:100;">
120
- </div>
121
-
122
- <div id="blazor-error-ui" role="alert" aria-live="assertive">
123
- <div class="blazor-error-ui__message"></div>
124
- <a href="." class="reload">Reload</a>
125
- <span class="dismiss">Dismiss</span>
126
- </div>
127
-
128
- <!-- Aggressively remove any existing service workers and caches so hosted deploys pick up new JS immediately -->
129
- <script>
130
- window.__swCleanup = (async () => {
131
- try {
132
- let hadAnything = false;
133
- if ('serviceWorker' in navigator) {
134
- const regs = await navigator.serviceWorker.getRegistrations();
135
- hadAnything = hadAnything || regs.length > 0;
136
- await Promise.allSettled(regs.map(r => r.unregister()));
137
- }
138
- if (window.caches) {
139
- const keys = await caches.keys();
140
- hadAnything = hadAnything || keys.length > 0;
141
- await Promise.allSettled(keys.map(k => caches.delete(k)));
142
- }
143
- return hadAnything;
144
- } catch (e) {
145
- console.debug('SW cleanup skipped:', e);
146
- return false;
147
- }
148
- })();
149
- </script>
150
-
151
- <!-- Blazor WASM loader (autostart disabled; we'll start after our scripts load) -->
152
- <script src="_framework/blazor.webassembly.js" autostart="false"></script>
153
-
154
- <!-- Global helpers and libraries -->
155
- <script src="js/marketing-tool.js"></script>
156
- <script>
157
- window.showBlazorBootError = function (message) {
158
- const errorUi = document.getElementById('blazor-error-ui');
159
- if (!errorUi) return;
160
-
161
- const messageElement = errorUi.querySelector('.blazor-error-ui__message');
162
- if (messageElement) {
163
- messageElement.textContent = message || 'This page could not finish loading.';
164
- }
165
-
166
- errorUi.classList.add('is-visible');
167
- errorUi.removeAttribute('hidden');
168
- };
169
-
170
- window.hideBlazorBootError = function () {
171
- const errorUi = document.getElementById('blazor-error-ui');
172
- if (!errorUi) return;
173
- errorUi.classList.remove('is-visible');
174
- };
175
-
176
- document.addEventListener('click', (event) => {
177
- const target = event.target;
178
- if (target instanceof HTMLElement && target.classList.contains('dismiss')) {
179
- window.hideBlazorBootError();
180
- }
181
- });
182
-
183
- // Global textarea handlers
184
- function adjustTextareaHeight(element) {
185
- if (!element) return;
186
-
187
- // ??좎뜦堉??[Change] Add jitter-prevention logic ??좎뜦堉??
188
- // Compare the previous text length. When content grows, skip the 'auto' reset.
189
- // Only reset to 'auto' when shrinking (during deletion).
190
- const currentLength = element.value.length;
191
- const prevLength = parseInt(element.dataset.prevLength || '0');
192
-
193
- if (currentLength < prevLength) {
194
- element.style.height = 'auto'; // reset height when deleting to allow shrink
195
- }
196
-
197
- element.dataset.prevLength = currentLength; // store current length
198
- // ??좎뜦堉??[Change] ??좎뜦堉??
199
-
200
- const computedStyles = window.getComputedStyle(element);
201
- const lineHeight = parseFloat(computedStyles.lineHeight || '24') || 24;
202
- const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;
203
- const paddingBottom = parseFloat(computedStyles.paddingBottom || '0') || 0;
204
- const verticalPadding = paddingTop + paddingBottom;
205
- const maxLines = 6; // limit to 6 lines
206
- const maxHeight = (lineHeight * maxLines) + verticalPadding;
207
- const minHeightPx = Math.max(lineHeight + verticalPadding, 42);
208
-
209
- const newHeight = Math.min(element.scrollHeight, maxHeight);
210
-
211
- // Even if content didn't shrink, apply if scrollHeight grew
212
- element.style.height = Math.max(newHeight, minHeightPx) + 'px';
213
- element.style.overflowY = 'hidden';
214
- }
215
- function resetTextareaHeight(element) {
216
- if (!element) return;
217
- const computedStyles = window.getComputedStyle(element);
218
- const lineHeight = parseFloat(computedStyles.lineHeight || '24') || 24;
219
- const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;
220
- const paddingBottom = parseFloat(computedStyles.paddingBottom || '0') || 0;
221
- const minHeightPx = Math.max(lineHeight + paddingTop + paddingBottom, 42);
222
- element.style.height = minHeightPx + 'px';
223
- element.style.overflowY = 'hidden';
224
- }
225
- function attachTextareaHandlers(element, dotNetRef) {
226
- if (!element) return;
227
-
228
- if (element.__mindexecEnterHandler) {
229
- element.removeEventListener('keydown', element.__mindexecEnterHandler);
230
- }
231
-
232
- const handleKeyDown = (e) => {
233
- if (e.key === 'Enter') {
234
- if (e.shiftKey) {
235
- return;
236
- }
237
-
238
- if (e.repeat || e.isComposing || e.keyCode === 229) {
239
- return;
240
- }
241
-
242
- e.preventDefault();
243
- const now = performance.now();
244
- if (element.__mindexecLastEnterAt && now - element.__mindexecLastEnterAt < 650) {
245
- return;
246
- }
247
-
248
- const promptSnapshot = element.value || '';
249
- if (!promptSnapshot.trim()) {
250
- return;
251
- }
252
-
253
- element.__mindexecLastEnterAt = now;
254
- const submitId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
255
- element.value = '';
256
- element.dispatchEvent(new Event('input', { bubbles: true }));
257
- resetTextareaHeight(element);
258
-
259
- if (dotNetRef && dotNetRef.invokeMethodAsync) {
260
- dotNetRef.invokeMethodAsync('OnGlobalInputEnterPressed', promptSnapshot, submitId)
261
- .catch((err) => console.warn('[GlobalInput] Enter submit failed:', err));
262
- }
263
- }
264
- };
265
-
266
- element.__mindexecEnterHandler = handleKeyDown;
267
- element.addEventListener('keydown', handleKeyDown);
268
- }
269
- function blurElement(element) {
270
- if (element) element.blur();
271
- if (document && document.body) document.body.focus();
272
- }
273
-
274
- function focusGlobalTextarea() {
275
- const textarea = document.getElementById('global-input-textarea');
276
- if (textarea) {
277
- textarea.focus();
278
- textarea.setSelectionRange(textarea.value.length, textarea.value.length);
279
- }
280
- }
281
-
282
- window.adjustTextareaHeight = adjustTextareaHeight;
283
- window.resetTextareaHeight = resetTextareaHeight;
284
- window.attachTextareaHandlers = attachTextareaHandlers;
285
- window.blurElement = blurElement;
286
- window.focusGlobalTextarea = focusGlobalTextarea;
287
-
288
- // Prevent default page-level DnD behavior
289
- document.addEventListener('dragover', (e) => {
290
- e.preventDefault();
291
- // ??좎뜦堉??[Change] Remove/avoid stopPropagation (do not disrupt event flow) ??좎뜦堉??
292
- // e.stopPropagation();
293
- // ??좎뜦堉??[Change] ??좎뜦堉??
294
-
295
- // ??좎뜦堉??[Change] Default is 'none', but only apply when not handled by children ??좎뜦堉??
296
- // (If MindMapDnD handles it, this code won't run or will be ignored)
297
- // e.dataTransfer.dropEffect = 'none';
298
- }, false);
299
-
300
- document.addEventListener('dragleave', (e) => {
301
- e.preventDefault();
302
- // e.stopPropagation(); // removed
303
- }, false);
304
-
305
- document.addEventListener('drop', (e) => {
306
- e.preventDefault();
307
- // e.stopPropagation(); // removed
308
- }, false);
309
- </script>
310
-
311
- <!-- Paddle.js -->
312
- <script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
313
-
314
- <!-- App scripts and libs REQUIRED before Blazor starts -->
315
- <script>
316
- window.mindExecutionStartupTiming = window.mindExecutionStartupTiming || (() => {
317
- const perf = window.performance;
318
- const now = () => perf && typeof perf.now === 'function'
319
- ? perf.now()
320
- : Date.now();
321
- const marks = new Map();
322
- const pageStart = now();
323
- marks.set('page-start', pageStart);
324
-
325
- function toDuration(value) {
326
- return `${Math.round(value)}ms`;
327
- }
328
-
329
- function formatDetails(details) {
330
- if (!details || typeof details !== 'object') {
331
- return '';
332
- }
333
-
334
- const parts = Object.entries(details)
335
- .filter(([, value]) => value !== undefined && value !== null && value !== '')
336
- .map(([key, value]) => `${key}=${typeof value === 'number' ? Math.round(value) : value}`);
337
-
338
- return parts.length > 0 ? ` | ${parts.join(', ')}` : '';
339
- }
340
-
341
- function elapsedSince(markName, currentNow) {
342
- const startedAt = marks.get(markName);
343
- return typeof startedAt === 'number' ? currentNow - startedAt : null;
344
- }
345
-
346
- return {
347
- mark(stage, details) {
348
- const currentNow = now();
349
- marks.set(stage, currentNow);
350
- const pageElapsed = elapsedSince('page-start', currentNow) ?? 0;
351
- try {
352
- window.dispatchEvent(new CustomEvent(`startup-timing:${stage}`, {
353
- detail: {
354
- stage,
355
- elapsedMs: Math.round(pageElapsed),
356
- details: details || null
357
- }
358
- }));
359
- } catch { }
360
- console.log(`[Startup Timing] ${stage}: ${toDuration(pageElapsed)} since page start${formatDetails(details)}`);
361
- return Math.round(pageElapsed);
362
- },
363
- logMindCanvasReady(details) {
364
- const currentNow = now();
365
- marks.set('mindcanvas-ready', currentNow);
366
-
367
- const segments = [];
368
- const pageElapsed = elapsedSince('page-start', currentNow);
369
- const scriptLoaderElapsed = elapsedSince('script-loader-start', currentNow);
370
- const blazorElapsed = elapsedSince('blazor-start', currentNow);
371
- const bootstrapElapsed = elapsedSince('mindcanvas-bootstrap-start', currentNow);
372
- const boardElapsed = elapsedSince('mindcanvas-board-load-start', currentNow);
373
-
374
- if (pageElapsed !== null) segments.push(`page=${toDuration(pageElapsed)}`);
375
- if (scriptLoaderElapsed !== null) segments.push(`scriptLoader=${toDuration(scriptLoaderElapsed)}`);
376
- if (blazorElapsed !== null) segments.push(`blazor=${toDuration(blazorElapsed)}`);
377
- if (bootstrapElapsed !== null) segments.push(`bootstrap=${toDuration(bootstrapElapsed)}`);
378
- if (boardElapsed !== null) segments.push(`board=${toDuration(boardElapsed)}`);
379
-
380
- try {
381
- window.dispatchEvent(new CustomEvent('startup-timing:mindcanvas-ready', {
382
- detail: {
383
- stage: 'mindcanvas-ready',
384
- elapsedMs: Math.round(pageElapsed ?? 0),
385
- details: details || null
386
- }
387
- }));
388
- } catch { }
389
-
390
- console.log(`[Startup Timing] MindCanvas ready: ${segments.join(' | ')}${formatDetails(details)}`);
391
- return Math.round(pageElapsed ?? 0);
392
- }
393
- };
394
- })();
395
- window.mindExecutionStartupTiming.mark('index-html-ready', {
396
- route: window.location.pathname || '/'
397
- });
398
-
399
- window.__marketingToolHosts = [
400
- 'mdview.pages.dev', 'mdview.mindexec.io', 'markdown-viewer.pages.dev', 'markdown-viewer.mindexec.io',
401
- 'bulkmd.pages.dev', 'bulkmd.mindexec.io', 'bulk-markdown-viewer.pages.dev', 'bulk-markdown-viewer.mindexec.io',
402
- 'mdoutln.pages.dev', 'mdoutln.mindexec.io', 'markdown-outline.pages.dev', 'markdown-outline.mindexec.io',
403
- 'mdtable.pages.dev', 'mdtable.mindexec.io', 'markdown-table-formatter.pages.dev', 'markdown-table-formatter.mindexec.io',
404
- 'readme.pages.dev', 'readme.mindexec.io', 'readme-previewer.pages.dev', 'readme-previewer.mindexec.io',
405
- 'md2html.pages.dev', 'md2html.mindexec.io', 'markdown-to-html.pages.dev', 'markdown-to-html.mindexec.io',
406
- 'mdcheck.pages.dev', 'mdcheck.mindexec.io', 'markdown-link-checker.pages.dev', 'markdown-link-checker.mindexec.io',
407
- 'quickpad.pages.dev', 'quickpad.mindexec.io', 'browser-notepad.pages.dev', 'browser-notepad.mindexec.io',
408
- 'clipbrd.pages.dev', 'clipbrd.mindexec.io', 'clipboard-board.pages.dev', 'clipboard-board.mindexec.io'
409
- ];
410
-
411
- window.__matchesMarketingToolHost = function (configuredHost, runtimeHost) {
412
- if (!configuredHost || !runtimeHost) {
413
- return false;
414
- }
415
-
416
- const normalizedConfiguredHost = configuredHost.toLowerCase();
417
- const normalizedRuntimeHost = runtimeHost.toLowerCase();
418
- if (normalizedConfiguredHost === normalizedRuntimeHost) {
419
- return true;
420
- }
421
-
422
- if (!normalizedConfiguredHost.endsWith('.pages.dev') || !normalizedRuntimeHost.endsWith('.pages.dev')) {
423
- return false;
424
- }
425
-
426
- const configuredPrefix = normalizedConfiguredHost.slice(0, -'.pages.dev'.length);
427
- const runtimePrefix = normalizedRuntimeHost.slice(0, -'.pages.dev'.length);
428
- return runtimePrefix === configuredPrefix || runtimePrefix.startsWith(`${configuredPrefix}-`);
429
- };
430
-
431
- window.__isMarketingToolHost = window.__marketingToolHosts.some(host =>
432
- window.__matchesMarketingToolHost(host, location.host || '')
433
- );
434
- </script>
435
- <!-- ??좎뜦堉??[Upgrade] Three.js r168 via ESM ??좎뜦堉??-->
436
- <script type="importmap">
437
- {
438
- "imports": {
439
- "three": "https://cdn.jsdelivr.net/npm/three@0.168.0/build/three.module.js"
440
- }
441
- }
442
- </script>
443
- <script type="module">
444
- if (!window.__isMarketingToolHost) {
445
- const THREE = await import('three');
446
-
447
- window.THREE = THREE;
448
- globalThis.THREE = THREE;
449
- console.log('[Three.js] r' + THREE.REVISION + ' loaded (ESM ??global)');
450
-
451
- window.THREE_LOADED = true;
452
- window.dispatchEvent(new Event('three-loaded'));
453
- } else {
454
- console.log('[Script Loader] Marketing tool host detected. Skipping Three.js preload.');
455
- }
456
- </script>
457
- <!-- Wait for THREE then load dependent scripts -->
458
- <script>
459
- function loadScript(src, options = {}) {
460
- const SCRIPT_LOAD_TIMEOUT_MS = 15000;
461
- const SCRIPT_LOAD_SLOW_MS = 3000;
462
- window.__mindExecutionScriptLoaderState = window.__mindExecutionScriptLoaderState || {
463
- pending: {},
464
- completed: [],
465
- lastError: null
466
- };
467
-
468
- const label = options.label || src;
469
- const startAt = performance.now();
470
- window.__mindExecutionScriptLoaderState.pending[label] = {
471
- src,
472
- label,
473
- startedAt: startAt
474
- };
475
-
476
- return new Promise((resolve, reject) => {
477
- const s = document.createElement('script');
478
- s.src = src;
479
- if (options.ordered === true) {
480
- // Ordered dynamic scripts still fetch in parallel, but execute in append order.
481
- s.async = false;
482
- }
483
- if (options.fetchPriority) {
484
- s.fetchPriority = options.fetchPriority;
485
- }
486
- let finished = false;
487
- const complete = (kind, error = null) => {
488
- if (finished) return;
489
- finished = true;
490
- clearTimeout(timeoutHandle);
491
-
492
- const elapsedMs = Math.max(0, performance.now() - startAt);
493
- delete window.__mindExecutionScriptLoaderState.pending[label];
494
-
495
- if (kind === 'load') {
496
- window.__mindExecutionScriptLoaderState.completed.push({
497
- label,
498
- elapsedMs: Math.round(elapsedMs),
499
- loadedAt: Date.now()
500
- });
501
- if (elapsedMs >= SCRIPT_LOAD_SLOW_MS) {
502
- console.warn(`[Script Loader] Slow script load: ${label} (${elapsedMs.toFixed(0)}ms)`);
503
- }
504
- resolve();
505
- return;
506
- }
507
-
508
- const pendingLabels = Object.keys(window.__mindExecutionScriptLoaderState.pending || {});
509
- const failure = error instanceof Error
510
- ? error
511
- : new Error(String(error || `Failed to load script: ${label}`));
512
- window.__mindExecutionScriptLoaderState.lastError = {
513
- label,
514
- src,
515
- kind,
516
- elapsedMs: Math.round(elapsedMs),
517
- pending: pendingLabels,
518
- message: failure.message
519
- };
520
- reject(failure);
521
- };
522
-
523
- const timeoutHandle = setTimeout(() => {
524
- const pendingLabels = Object.keys(window.__mindExecutionScriptLoaderState.pending || {});
525
- complete('timeout', new Error(`[Script Loader] Timeout waiting for ${label} after ${SCRIPT_LOAD_TIMEOUT_MS}ms | pending=${pendingLabels.join(', ') || '-'}`));
526
- }, options.timeoutMs || SCRIPT_LOAD_TIMEOUT_MS);
527
-
528
- s.onload = () => complete('load');
529
- s.onerror = () => complete('error', new Error(`[Script Loader] Failed to load ${label}`));
530
- document.head.appendChild(s);
531
- });
532
- }
533
-
534
- function loadScriptBatchOrdered(scripts, scriptUrl, onLoaded) {
535
- const scriptPromises = [];
536
-
537
- for (const script of scripts) {
538
- const promise = loadScript(scriptUrl(script), {
539
- ordered: true,
540
- fetchPriority: 'high',
541
- label: script
542
- }).then(() => {
543
- onLoaded?.(script);
544
- });
545
-
546
- scriptPromises.push(promise);
547
- }
548
-
549
- return Promise.all(scriptPromises);
550
- }
551
-
552
- async function loadDependentScripts() {
553
- window.mindExecutionStartupTiming?.mark('script-loader-start', {
554
- route: window.location.pathname || '/'
555
- });
556
-
557
- if (window.__isMarketingToolHost) {
558
- console.log('[Script Loader] Marketing tool host detected. Skipping MindMap script bundle.');
559
-
560
- try {
561
- if (window.__swCleanup) {
562
- const cleaned = await window.__swCleanup;
563
- const flag = '__swCleanedOnce';
564
- if (cleaned && !sessionStorage.getItem(flag)) {
565
- sessionStorage.setItem(flag, '1');
566
- location.reload();
567
- return;
568
- }
569
- }
570
- } catch { }
571
-
572
- if (window.Blazor && Blazor.start) {
573
- window.mindExecutionStartupTiming?.mark('blazor-start', { marketingToolHost: true });
574
- await Blazor.start();
575
- }
576
-
577
- return;
578
- }
579
-
580
- // Wait for THREE to be available
581
- if (!window.THREE_LOADED) {
582
- await new Promise(r => window.addEventListener('three-loaded', r, { once: true }));
583
- }
584
-
585
- const base = '_content/MindExecution.Shared/js/';
586
- const scriptVersion = '20260802-remote-work-v963';
587
- const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
588
- console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
589
- const criticalScripts = [
590
- 'mind-map-dev-guards.js',
591
- 'renderers/CSS3DRenderer.js',
592
- 'helpers/InfiniteGridHelper.js',
593
- 'marked.min.js',
594
- 'background-themes.js',
595
- 'mind-map-logic-workers.js',
596
- // Troika removed
16
+ <!-- ??좎뜦堉??Font Awesome (local) ??좎뜦堉??-->
17
+ <link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
18
+ <!-- ??좎뜦堉??-->
19
+ <style>
20
+ #app {
21
+ min-height: 100vh;
22
+ }
23
+
24
+ .app-static-fallback {
25
+ width: min(960px, calc(100% - 32px));
26
+ margin: 0 auto;
27
+ padding: 56px 0 48px;
28
+ color: #0f172a;
29
+ line-height: 1.7;
30
+ }
31
+
32
+ .app-static-fallback__eyebrow {
33
+ display: inline-flex;
34
+ padding: 6px 10px;
35
+ border-radius: 999px;
36
+ background: rgba(255, 255, 255, 0.84);
37
+ border: 1px solid rgba(148, 163, 184, 0.25);
38
+ font-size: 12px;
39
+ font-weight: 700;
40
+ color: #334155;
41
+ }
42
+
43
+ .app-static-fallback h1 {
44
+ margin: 16px 0 0;
45
+ font-size: clamp(30px, 4vw, 48px);
46
+ line-height: 1.05;
47
+ font-weight: 800;
48
+ }
49
+
50
+ .app-static-fallback p {
51
+ max-width: 760px;
52
+ margin: 16px 0 0;
53
+ color: #475569;
54
+ }
55
+
56
+ .app-static-fallback a {
57
+ color: #0f172a;
58
+ font-weight: 700;
59
+ }
60
+
61
+ #blazor-error-ui {
62
+ display: none;
63
+ }
64
+
65
+ #blazor-error-ui.is-visible {
66
+ position: fixed;
67
+ right: 20px;
68
+ bottom: 20px;
69
+ z-index: 9999;
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 12px;
73
+ max-width: 420px;
74
+ padding: 14px 16px;
75
+ border-radius: 14px;
76
+ background: rgba(15, 23, 42, 0.96);
77
+ color: #fff;
78
+ box-shadow: 0 18px 48px rgba(15, 23, 42, 0.28);
79
+ }
80
+
81
+ .blazor-error-ui__message {
82
+ flex: 1;
83
+ font-size: 14px;
84
+ line-height: 1.6;
85
+ }
86
+
87
+ #blazor-error-ui .reload,
88
+ #blazor-error-ui .dismiss {
89
+ color: #fff;
90
+ font-size: 13px;
91
+ font-weight: 700;
92
+ text-decoration: none;
93
+ cursor: pointer;
94
+ }
95
+ </style>
96
+ </head>
97
+
98
+ <body>
99
+ <div id="app-container">
100
+ <div id="app">
101
+ <article class="app-static-fallback" id="app-static-fallback">
102
+ <div class="app-static-fallback__eyebrow">MindExec</div>
103
+ <h1>MindExec</h1>
104
+ <p>Turn ideas into revenue execution. MindExec is a Business Execution OS that moves serious work into MindCanvas, where context, AI Tasks, execution Skills, media, and results stay connected.</p>
105
+ <p><a href="/mindcanvas">Open MindCanvas</a> | <a href="/pricing">See pricing</a> | <a href="/tools">Browse free tools</a></p>
106
+ <noscript>
107
+ <p>JavaScript is required for the interactive tool experience.</p>
108
+ </noscript>
109
+ </article>
110
+ </div>
111
+ </div>
112
+
113
+ <div id="three-js-container"
114
+ style="display: none; position: fixed; top:0; left:0; width:100%; height:100%; z-index:999; background-color: rgba(0,0,0,0.5);">
115
+ </div>
116
+
117
+ <!-- Selection rectangle overlay -->
118
+ <div id="selection-rectangle"
119
+ style="position: fixed; border:2px solid #1173d4; background-color: rgba(17, 115, 212, 0.15); pointer-events: none; display: none; z-index:100;">
120
+ </div>
121
+
122
+ <div id="blazor-error-ui" role="alert" aria-live="assertive">
123
+ <div class="blazor-error-ui__message"></div>
124
+ <a href="." class="reload">Reload</a>
125
+ <span class="dismiss">Dismiss</span>
126
+ </div>
127
+
128
+ <!-- Aggressively remove any existing service workers and caches so hosted deploys pick up new JS immediately -->
129
+ <script>
130
+ window.__swCleanup = (async () => {
131
+ try {
132
+ let hadAnything = false;
133
+ if ('serviceWorker' in navigator) {
134
+ const regs = await navigator.serviceWorker.getRegistrations();
135
+ hadAnything = hadAnything || regs.length > 0;
136
+ await Promise.allSettled(regs.map(r => r.unregister()));
137
+ }
138
+ if (window.caches) {
139
+ const keys = await caches.keys();
140
+ hadAnything = hadAnything || keys.length > 0;
141
+ await Promise.allSettled(keys.map(k => caches.delete(k)));
142
+ }
143
+ return hadAnything;
144
+ } catch (e) {
145
+ console.debug('SW cleanup skipped:', e);
146
+ return false;
147
+ }
148
+ })();
149
+ </script>
150
+
151
+ <!-- Blazor WASM loader (autostart disabled; we'll start after our scripts load) -->
152
+ <script src="_framework/blazor.webassembly.js" autostart="false"></script>
153
+
154
+ <!-- Global helpers and libraries -->
155
+ <script src="js/marketing-tool.js"></script>
156
+ <script>
157
+ window.showBlazorBootError = function (message) {
158
+ const errorUi = document.getElementById('blazor-error-ui');
159
+ if (!errorUi) return;
160
+
161
+ const messageElement = errorUi.querySelector('.blazor-error-ui__message');
162
+ if (messageElement) {
163
+ messageElement.textContent = message || 'This page could not finish loading.';
164
+ }
165
+
166
+ errorUi.classList.add('is-visible');
167
+ errorUi.removeAttribute('hidden');
168
+ };
169
+
170
+ window.hideBlazorBootError = function () {
171
+ const errorUi = document.getElementById('blazor-error-ui');
172
+ if (!errorUi) return;
173
+ errorUi.classList.remove('is-visible');
174
+ };
175
+
176
+ document.addEventListener('click', (event) => {
177
+ const target = event.target;
178
+ if (target instanceof HTMLElement && target.classList.contains('dismiss')) {
179
+ window.hideBlazorBootError();
180
+ }
181
+ });
182
+
183
+ // Global textarea handlers
184
+ function adjustTextareaHeight(element) {
185
+ if (!element) return;
186
+
187
+ // ??좎뜦堉??[Change] Add jitter-prevention logic ??좎뜦堉??
188
+ // Compare the previous text length. When content grows, skip the 'auto' reset.
189
+ // Only reset to 'auto' when shrinking (during deletion).
190
+ const currentLength = element.value.length;
191
+ const prevLength = parseInt(element.dataset.prevLength || '0');
192
+
193
+ if (currentLength < prevLength) {
194
+ element.style.height = 'auto'; // reset height when deleting to allow shrink
195
+ }
196
+
197
+ element.dataset.prevLength = currentLength; // store current length
198
+ // ??좎뜦堉??[Change] ??좎뜦堉??
199
+
200
+ const computedStyles = window.getComputedStyle(element);
201
+ const lineHeight = parseFloat(computedStyles.lineHeight || '24') || 24;
202
+ const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;
203
+ const paddingBottom = parseFloat(computedStyles.paddingBottom || '0') || 0;
204
+ const verticalPadding = paddingTop + paddingBottom;
205
+ const maxLines = 6; // limit to 6 lines
206
+ const maxHeight = (lineHeight * maxLines) + verticalPadding;
207
+ const minHeightPx = Math.max(lineHeight + verticalPadding, 42);
208
+
209
+ const newHeight = Math.min(element.scrollHeight, maxHeight);
210
+
211
+ // Even if content didn't shrink, apply if scrollHeight grew
212
+ element.style.height = Math.max(newHeight, minHeightPx) + 'px';
213
+ element.style.overflowY = 'hidden';
214
+ }
215
+ function resetTextareaHeight(element) {
216
+ if (!element) return;
217
+ const computedStyles = window.getComputedStyle(element);
218
+ const lineHeight = parseFloat(computedStyles.lineHeight || '24') || 24;
219
+ const paddingTop = parseFloat(computedStyles.paddingTop || '0') || 0;
220
+ const paddingBottom = parseFloat(computedStyles.paddingBottom || '0') || 0;
221
+ const minHeightPx = Math.max(lineHeight + paddingTop + paddingBottom, 42);
222
+ element.style.height = minHeightPx + 'px';
223
+ element.style.overflowY = 'hidden';
224
+ }
225
+ function attachTextareaHandlers(element, dotNetRef) {
226
+ if (!element) return;
227
+
228
+ if (element.__mindexecEnterHandler) {
229
+ element.removeEventListener('keydown', element.__mindexecEnterHandler);
230
+ }
231
+
232
+ const handleKeyDown = (e) => {
233
+ if (e.key === 'Enter') {
234
+ if (e.shiftKey) {
235
+ return;
236
+ }
237
+
238
+ if (e.repeat || e.isComposing || e.keyCode === 229) {
239
+ return;
240
+ }
241
+
242
+ e.preventDefault();
243
+ const now = performance.now();
244
+ if (element.__mindexecLastEnterAt && now - element.__mindexecLastEnterAt < 650) {
245
+ return;
246
+ }
247
+
248
+ const promptSnapshot = element.value || '';
249
+ if (!promptSnapshot.trim()) {
250
+ return;
251
+ }
252
+
253
+ element.__mindexecLastEnterAt = now;
254
+ const submitId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
255
+ element.value = '';
256
+ element.dispatchEvent(new Event('input', { bubbles: true }));
257
+ resetTextareaHeight(element);
258
+
259
+ if (dotNetRef && dotNetRef.invokeMethodAsync) {
260
+ dotNetRef.invokeMethodAsync('OnGlobalInputEnterPressed', promptSnapshot, submitId)
261
+ .catch((err) => console.warn('[GlobalInput] Enter submit failed:', err));
262
+ }
263
+ }
264
+ };
265
+
266
+ element.__mindexecEnterHandler = handleKeyDown;
267
+ element.addEventListener('keydown', handleKeyDown);
268
+ }
269
+ function blurElement(element) {
270
+ if (element) element.blur();
271
+ if (document && document.body) document.body.focus();
272
+ }
273
+
274
+ function focusGlobalTextarea() {
275
+ const textarea = document.getElementById('global-input-textarea');
276
+ if (textarea) {
277
+ textarea.focus();
278
+ textarea.setSelectionRange(textarea.value.length, textarea.value.length);
279
+ }
280
+ }
281
+
282
+ window.adjustTextareaHeight = adjustTextareaHeight;
283
+ window.resetTextareaHeight = resetTextareaHeight;
284
+ window.attachTextareaHandlers = attachTextareaHandlers;
285
+ window.blurElement = blurElement;
286
+ window.focusGlobalTextarea = focusGlobalTextarea;
287
+
288
+ // Prevent default page-level DnD behavior
289
+ document.addEventListener('dragover', (e) => {
290
+ e.preventDefault();
291
+ // ??좎뜦堉??[Change] Remove/avoid stopPropagation (do not disrupt event flow) ??좎뜦堉??
292
+ // e.stopPropagation();
293
+ // ??좎뜦堉??[Change] ??좎뜦堉??
294
+
295
+ // ??좎뜦堉??[Change] Default is 'none', but only apply when not handled by children ??좎뜦堉??
296
+ // (If MindMapDnD handles it, this code won't run or will be ignored)
297
+ // e.dataTransfer.dropEffect = 'none';
298
+ }, false);
299
+
300
+ document.addEventListener('dragleave', (e) => {
301
+ e.preventDefault();
302
+ // e.stopPropagation(); // removed
303
+ }, false);
304
+
305
+ document.addEventListener('drop', (e) => {
306
+ e.preventDefault();
307
+ // e.stopPropagation(); // removed
308
+ }, false);
309
+ </script>
310
+
311
+ <!-- Paddle.js -->
312
+ <script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
313
+
314
+ <!-- App scripts and libs REQUIRED before Blazor starts -->
315
+ <script>
316
+ window.mindExecutionStartupTiming = window.mindExecutionStartupTiming || (() => {
317
+ const perf = window.performance;
318
+ const now = () => perf && typeof perf.now === 'function'
319
+ ? perf.now()
320
+ : Date.now();
321
+ const marks = new Map();
322
+ const pageStart = now();
323
+ marks.set('page-start', pageStart);
324
+
325
+ function toDuration(value) {
326
+ return `${Math.round(value)}ms`;
327
+ }
328
+
329
+ function formatDetails(details) {
330
+ if (!details || typeof details !== 'object') {
331
+ return '';
332
+ }
333
+
334
+ const parts = Object.entries(details)
335
+ .filter(([, value]) => value !== undefined && value !== null && value !== '')
336
+ .map(([key, value]) => `${key}=${typeof value === 'number' ? Math.round(value) : value}`);
337
+
338
+ return parts.length > 0 ? ` | ${parts.join(', ')}` : '';
339
+ }
340
+
341
+ function elapsedSince(markName, currentNow) {
342
+ const startedAt = marks.get(markName);
343
+ return typeof startedAt === 'number' ? currentNow - startedAt : null;
344
+ }
345
+
346
+ return {
347
+ mark(stage, details) {
348
+ const currentNow = now();
349
+ marks.set(stage, currentNow);
350
+ const pageElapsed = elapsedSince('page-start', currentNow) ?? 0;
351
+ try {
352
+ window.dispatchEvent(new CustomEvent(`startup-timing:${stage}`, {
353
+ detail: {
354
+ stage,
355
+ elapsedMs: Math.round(pageElapsed),
356
+ details: details || null
357
+ }
358
+ }));
359
+ } catch { }
360
+ console.log(`[Startup Timing] ${stage}: ${toDuration(pageElapsed)} since page start${formatDetails(details)}`);
361
+ return Math.round(pageElapsed);
362
+ },
363
+ logMindCanvasReady(details) {
364
+ const currentNow = now();
365
+ marks.set('mindcanvas-ready', currentNow);
366
+
367
+ const segments = [];
368
+ const pageElapsed = elapsedSince('page-start', currentNow);
369
+ const scriptLoaderElapsed = elapsedSince('script-loader-start', currentNow);
370
+ const blazorElapsed = elapsedSince('blazor-start', currentNow);
371
+ const bootstrapElapsed = elapsedSince('mindcanvas-bootstrap-start', currentNow);
372
+ const boardElapsed = elapsedSince('mindcanvas-board-load-start', currentNow);
373
+
374
+ if (pageElapsed !== null) segments.push(`page=${toDuration(pageElapsed)}`);
375
+ if (scriptLoaderElapsed !== null) segments.push(`scriptLoader=${toDuration(scriptLoaderElapsed)}`);
376
+ if (blazorElapsed !== null) segments.push(`blazor=${toDuration(blazorElapsed)}`);
377
+ if (bootstrapElapsed !== null) segments.push(`bootstrap=${toDuration(bootstrapElapsed)}`);
378
+ if (boardElapsed !== null) segments.push(`board=${toDuration(boardElapsed)}`);
379
+
380
+ try {
381
+ window.dispatchEvent(new CustomEvent('startup-timing:mindcanvas-ready', {
382
+ detail: {
383
+ stage: 'mindcanvas-ready',
384
+ elapsedMs: Math.round(pageElapsed ?? 0),
385
+ details: details || null
386
+ }
387
+ }));
388
+ } catch { }
389
+
390
+ console.log(`[Startup Timing] MindCanvas ready: ${segments.join(' | ')}${formatDetails(details)}`);
391
+ return Math.round(pageElapsed ?? 0);
392
+ }
393
+ };
394
+ })();
395
+ window.mindExecutionStartupTiming.mark('index-html-ready', {
396
+ route: window.location.pathname || '/'
397
+ });
398
+
399
+ window.__marketingToolHosts = [
400
+ 'mdview.pages.dev', 'mdview.mindexec.io', 'markdown-viewer.pages.dev', 'markdown-viewer.mindexec.io',
401
+ 'bulkmd.pages.dev', 'bulkmd.mindexec.io', 'bulk-markdown-viewer.pages.dev', 'bulk-markdown-viewer.mindexec.io',
402
+ 'mdoutln.pages.dev', 'mdoutln.mindexec.io', 'markdown-outline.pages.dev', 'markdown-outline.mindexec.io',
403
+ 'mdtable.pages.dev', 'mdtable.mindexec.io', 'markdown-table-formatter.pages.dev', 'markdown-table-formatter.mindexec.io',
404
+ 'readme.pages.dev', 'readme.mindexec.io', 'readme-previewer.pages.dev', 'readme-previewer.mindexec.io',
405
+ 'md2html.pages.dev', 'md2html.mindexec.io', 'markdown-to-html.pages.dev', 'markdown-to-html.mindexec.io',
406
+ 'mdcheck.pages.dev', 'mdcheck.mindexec.io', 'markdown-link-checker.pages.dev', 'markdown-link-checker.mindexec.io',
407
+ 'quickpad.pages.dev', 'quickpad.mindexec.io', 'browser-notepad.pages.dev', 'browser-notepad.mindexec.io',
408
+ 'clipbrd.pages.dev', 'clipbrd.mindexec.io', 'clipboard-board.pages.dev', 'clipboard-board.mindexec.io'
409
+ ];
410
+
411
+ window.__matchesMarketingToolHost = function (configuredHost, runtimeHost) {
412
+ if (!configuredHost || !runtimeHost) {
413
+ return false;
414
+ }
415
+
416
+ const normalizedConfiguredHost = configuredHost.toLowerCase();
417
+ const normalizedRuntimeHost = runtimeHost.toLowerCase();
418
+ if (normalizedConfiguredHost === normalizedRuntimeHost) {
419
+ return true;
420
+ }
421
+
422
+ if (!normalizedConfiguredHost.endsWith('.pages.dev') || !normalizedRuntimeHost.endsWith('.pages.dev')) {
423
+ return false;
424
+ }
425
+
426
+ const configuredPrefix = normalizedConfiguredHost.slice(0, -'.pages.dev'.length);
427
+ const runtimePrefix = normalizedRuntimeHost.slice(0, -'.pages.dev'.length);
428
+ return runtimePrefix === configuredPrefix || runtimePrefix.startsWith(`${configuredPrefix}-`);
429
+ };
430
+
431
+ window.__isMarketingToolHost = window.__marketingToolHosts.some(host =>
432
+ window.__matchesMarketingToolHost(host, location.host || '')
433
+ );
434
+ </script>
435
+ <!-- ??좎뜦堉??[Upgrade] Three.js r168 via ESM ??좎뜦堉??-->
436
+ <script type="importmap">
437
+ {
438
+ "imports": {
439
+ "three": "https://cdn.jsdelivr.net/npm/three@0.168.0/build/three.module.js"
440
+ }
441
+ }
442
+ </script>
443
+ <script type="module">
444
+ if (!window.__isMarketingToolHost) {
445
+ const THREE = await import('three');
446
+
447
+ window.THREE = THREE;
448
+ globalThis.THREE = THREE;
449
+ console.log('[Three.js] r' + THREE.REVISION + ' loaded (ESM ??global)');
450
+
451
+ window.THREE_LOADED = true;
452
+ window.dispatchEvent(new Event('three-loaded'));
453
+ } else {
454
+ console.log('[Script Loader] Marketing tool host detected. Skipping Three.js preload.');
455
+ }
456
+ </script>
457
+ <!-- Wait for THREE then load dependent scripts -->
458
+ <script>
459
+ function loadScript(src, options = {}) {
460
+ const SCRIPT_LOAD_TIMEOUT_MS = 15000;
461
+ const SCRIPT_LOAD_SLOW_MS = 3000;
462
+ window.__mindExecutionScriptLoaderState = window.__mindExecutionScriptLoaderState || {
463
+ pending: {},
464
+ completed: [],
465
+ lastError: null
466
+ };
467
+
468
+ const label = options.label || src;
469
+ const startAt = performance.now();
470
+ window.__mindExecutionScriptLoaderState.pending[label] = {
471
+ src,
472
+ label,
473
+ startedAt: startAt
474
+ };
475
+
476
+ return new Promise((resolve, reject) => {
477
+ const s = document.createElement('script');
478
+ s.src = src;
479
+ if (options.ordered === true) {
480
+ // Ordered dynamic scripts still fetch in parallel, but execute in append order.
481
+ s.async = false;
482
+ }
483
+ if (options.fetchPriority) {
484
+ s.fetchPriority = options.fetchPriority;
485
+ }
486
+ let finished = false;
487
+ const complete = (kind, error = null) => {
488
+ if (finished) return;
489
+ finished = true;
490
+ clearTimeout(timeoutHandle);
491
+
492
+ const elapsedMs = Math.max(0, performance.now() - startAt);
493
+ delete window.__mindExecutionScriptLoaderState.pending[label];
494
+
495
+ if (kind === 'load') {
496
+ window.__mindExecutionScriptLoaderState.completed.push({
497
+ label,
498
+ elapsedMs: Math.round(elapsedMs),
499
+ loadedAt: Date.now()
500
+ });
501
+ if (elapsedMs >= SCRIPT_LOAD_SLOW_MS) {
502
+ console.warn(`[Script Loader] Slow script load: ${label} (${elapsedMs.toFixed(0)}ms)`);
503
+ }
504
+ resolve();
505
+ return;
506
+ }
507
+
508
+ const pendingLabels = Object.keys(window.__mindExecutionScriptLoaderState.pending || {});
509
+ const failure = error instanceof Error
510
+ ? error
511
+ : new Error(String(error || `Failed to load script: ${label}`));
512
+ window.__mindExecutionScriptLoaderState.lastError = {
513
+ label,
514
+ src,
515
+ kind,
516
+ elapsedMs: Math.round(elapsedMs),
517
+ pending: pendingLabels,
518
+ message: failure.message
519
+ };
520
+ reject(failure);
521
+ };
522
+
523
+ const timeoutHandle = setTimeout(() => {
524
+ const pendingLabels = Object.keys(window.__mindExecutionScriptLoaderState.pending || {});
525
+ complete('timeout', new Error(`[Script Loader] Timeout waiting for ${label} after ${SCRIPT_LOAD_TIMEOUT_MS}ms | pending=${pendingLabels.join(', ') || '-'}`));
526
+ }, options.timeoutMs || SCRIPT_LOAD_TIMEOUT_MS);
527
+
528
+ s.onload = () => complete('load');
529
+ s.onerror = () => complete('error', new Error(`[Script Loader] Failed to load ${label}`));
530
+ document.head.appendChild(s);
531
+ });
532
+ }
533
+
534
+ function loadScriptBatchOrdered(scripts, scriptUrl, onLoaded) {
535
+ const scriptPromises = [];
536
+
537
+ for (const script of scripts) {
538
+ const promise = loadScript(scriptUrl(script), {
539
+ ordered: true,
540
+ fetchPriority: 'high',
541
+ label: script
542
+ }).then(() => {
543
+ onLoaded?.(script);
544
+ });
545
+
546
+ scriptPromises.push(promise);
547
+ }
548
+
549
+ return Promise.all(scriptPromises);
550
+ }
551
+
552
+ async function loadDependentScripts() {
553
+ window.mindExecutionStartupTiming?.mark('script-loader-start', {
554
+ route: window.location.pathname || '/'
555
+ });
556
+
557
+ if (window.__isMarketingToolHost) {
558
+ console.log('[Script Loader] Marketing tool host detected. Skipping MindMap script bundle.');
559
+
560
+ try {
561
+ if (window.__swCleanup) {
562
+ const cleaned = await window.__swCleanup;
563
+ const flag = '__swCleanedOnce';
564
+ if (cleaned && !sessionStorage.getItem(flag)) {
565
+ sessionStorage.setItem(flag, '1');
566
+ location.reload();
567
+ return;
568
+ }
569
+ }
570
+ } catch { }
571
+
572
+ if (window.Blazor && Blazor.start) {
573
+ window.mindExecutionStartupTiming?.mark('blazor-start', { marketingToolHost: true });
574
+ await Blazor.start();
575
+ }
576
+
577
+ return;
578
+ }
579
+
580
+ // Wait for THREE to be available
581
+ if (!window.THREE_LOADED) {
582
+ await new Promise(r => window.addEventListener('three-loaded', r, { once: true }));
583
+ }
584
+
585
+ const base = '_content/MindExecution.Shared/js/';
586
+ const scriptVersion = '20260806-thumbnail-agents-v964';
587
+ const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
588
+ console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
589
+ const criticalScripts = [
590
+ 'mind-map-dev-guards.js',
591
+ 'renderers/CSS3DRenderer.js',
592
+ 'helpers/InfiniteGridHelper.js',
593
+ 'marked.min.js',
594
+ 'background-themes.js',
595
+ 'mind-map-logic-workers.js',
596
+ // Troika removed
597
597
  'texture-worker-manager.js', // ??Web Worker ??좎럩?ゅ뜝???좎럩苑?
598
- 'mind-map-texture-factory.js',
598
+ 'mind-map-texture-factory.js',
599
599
  'mind-map-glow-shader.js', // ??SDF Glow (no textures, GPU only)
600
600
  'mind-map-video-playback-controls.js',
601
601
  'mind-map-remote-codecs.js',
602
602
  'mind-map-css3d-hotpath.js',
603
603
  'mind-map-css3d-manager.js',
604
604
  'mind-map-object-manager.js',
605
- 'mind-map-pipeline.js',
606
- 'mind-map-nodes.js',
607
- 'mind-map-menu-manager.js',
608
- 'mind-map-multi-select.js',
605
+ 'mind-map-pipeline.js',
606
+ 'mind-map-nodes.js',
607
+ 'mind-map-menu-manager.js',
608
+ 'mind-map-multi-select.js',
609
609
  'mind-map-interactions.js',
610
610
  'mind-map-dnd.js',
611
611
  'mind-map-render-plan.js',
612
612
  'mind-map-normal-boundary-optimizer.js',
613
613
  'mind-map-lod-video-placeholder.js',
614
614
  'mind-map-lod-renderer.js',
615
- 'mind-map-text-lod-system.js', // ??Text LOD ??좎럩???(??좎럩????좎럩?ゅ뜝???좎럩彛?
616
- 'mind-map-core.js',
617
- 'mindmap-toolbar.js',
618
- 'token-manager.js',
619
- 'file-system-helper.js'
620
- ];
621
- const routePath = (location.pathname || '/').toLowerCase();
622
- const routeCriticalScripts = [];
623
- if (routePath === '/code' || routePath === '/agent') {
624
- routeCriticalScripts.push('code-master.js', 'agent-visualization.js');
625
- }
626
- if (routePath === '/planmaster' || routePath === '/planagent') {
627
- routeCriticalScripts.push('plan-master.js');
628
- }
629
- const deferredScripts = ['plan-master.js', 'code-master.js', 'agent-visualization.js']
630
- .filter(script => !routeCriticalScripts.includes(script));
631
-
632
- function queueAgentSettings(globalName, pendingKey) {
633
- if (window[globalName]) return;
634
- window[globalName] = {
635
- applySettings(settings) {
636
- window[pendingKey] = Object.assign({}, window[pendingKey] || {}, settings || {});
637
- }
638
- };
639
- }
640
-
641
- function flushQueuedAgentSettings(script) {
642
- const mappings = {
643
- 'plan-master.js': ['planAgent', '__pendingPlanAgentSettings'],
644
- 'code-master.js': ['codeAgent', '__pendingCodeAgentSettings']
645
- };
646
- const mapping = mappings[script];
647
- if (!mapping) return;
648
-
649
- const [globalName, pendingKey] = mapping;
650
- const pending = window[pendingKey];
651
- if (pending && window[globalName]?.applySettings) {
652
- window[pendingKey] = null;
653
- window[globalName].applySettings(pending);
654
- }
655
- }
656
-
657
- queueAgentSettings('planAgent', '__pendingPlanAgentSettings');
658
- queueAgentSettings('codeAgent', '__pendingCodeAgentSettings');
659
-
660
- await loadScriptBatchOrdered(
661
- [...criticalScripts, ...routeCriticalScripts],
662
- scriptUrl,
663
- flushQueuedAgentSettings
664
- );
665
-
666
- window.MindCanvasBuildInfo?.setRuntime?.('scriptVersion', scriptVersion);
615
+ 'mind-map-text-lod-system.js', // ??Text LOD ??좎럩???(??좎럩????좎럩?ゅ뜝???좎럩彛?
616
+ 'mind-map-core.js',
617
+ 'mindmap-toolbar.js',
618
+ 'token-manager.js',
619
+ 'file-system-helper.js'
620
+ ];
621
+ const routePath = (location.pathname || '/').toLowerCase();
622
+ const routeCriticalScripts = [];
623
+ if (routePath === '/code' || routePath === '/agent') {
624
+ routeCriticalScripts.push('code-master.js', 'agent-visualization.js');
625
+ }
626
+ if (routePath === '/planmaster' || routePath === '/planagent') {
627
+ routeCriticalScripts.push('plan-master.js');
628
+ }
629
+ const deferredScripts = ['plan-master.js', 'code-master.js', 'agent-visualization.js']
630
+ .filter(script => !routeCriticalScripts.includes(script));
631
+
632
+ function queueAgentSettings(globalName, pendingKey) {
633
+ if (window[globalName]) return;
634
+ window[globalName] = {
635
+ applySettings(settings) {
636
+ window[pendingKey] = Object.assign({}, window[pendingKey] || {}, settings || {});
637
+ }
638
+ };
639
+ }
640
+
641
+ function flushQueuedAgentSettings(script) {
642
+ const mappings = {
643
+ 'plan-master.js': ['planAgent', '__pendingPlanAgentSettings'],
644
+ 'code-master.js': ['codeAgent', '__pendingCodeAgentSettings']
645
+ };
646
+ const mapping = mappings[script];
647
+ if (!mapping) return;
648
+
649
+ const [globalName, pendingKey] = mapping;
650
+ const pending = window[pendingKey];
651
+ if (pending && window[globalName]?.applySettings) {
652
+ window[pendingKey] = null;
653
+ window[globalName].applySettings(pending);
654
+ }
655
+ }
656
+
657
+ queueAgentSettings('planAgent', '__pendingPlanAgentSettings');
658
+ queueAgentSettings('codeAgent', '__pendingCodeAgentSettings');
659
+
660
+ await loadScriptBatchOrdered(
661
+ [...criticalScripts, ...routeCriticalScripts],
662
+ scriptUrl,
663
+ flushQueuedAgentSettings
664
+ );
665
+
666
+ window.MindCanvasBuildInfo?.setRuntime?.('scriptVersion', scriptVersion);
667
667
  window.MindCanvasBuildInfo?.validateRequiredParts?.(['devGuards', 'renderPlan', 'normalBoundaryOptimizer', 'core', 'lodRenderer']);
668
-
669
- console.log('[Script Loader] Critical scripts loaded, starting Blazor...');
670
- window.mindExecutionStartupTiming?.mark('critical-scripts-loaded', {
671
- criticalCount: criticalScripts.length + routeCriticalScripts.length
672
- });
673
-
674
- // SW cleanup
675
- try {
676
- if (window.__swCleanup) {
677
- const cleaned = await window.__swCleanup;
678
- const flag = '__swCleanedOnce';
679
- if (cleaned && !sessionStorage.getItem(flag)) {
680
- sessionStorage.setItem(flag, '1');
681
- location.reload();
682
- return;
683
- }
684
- }
685
- } catch { }
686
-
687
- // Start Blazor
688
- if (window.Blazor && Blazor.start) {
689
- window.mindExecutionStartupTiming?.mark('blazor-start', { marketingToolHost: false });
690
- await Blazor.start();
691
- }
692
-
693
- const scheduleDeferredScripts = window.requestIdleCallback
694
- ? ((callback) => window.requestIdleCallback(callback, { timeout: 1500 }))
695
- : ((callback) => setTimeout(callback, 0));
696
-
697
- const loadDeferredScriptsNow = () => {
698
- scheduleDeferredScripts(() => {
699
- (async () => {
700
- await loadScriptBatchOrdered(
701
- deferredScripts,
702
- scriptUrl,
703
- flushQueuedAgentSettings
704
- );
705
- console.log('[Script Loader] Deferred scripts loaded.');
706
- window.mindExecutionStartupTiming?.mark('deferred-scripts-loaded', {
707
- deferredCount: deferredScripts.length
708
- });
709
- })().catch(e => console.error('[Script Loader] Deferred load failed:', e));
710
- });
711
- };
712
-
713
- if (routePath === '/mindcanvas' && deferredScripts.length > 0) {
714
- let deferredStarted = false;
715
- const startDeferredAfterMindCanvasReady = () => {
716
- if (deferredStarted) return;
717
- deferredStarted = true;
718
- loadDeferredScriptsNow();
719
- };
720
-
721
- window.addEventListener('startup-timing:mindcanvas-ready', startDeferredAfterMindCanvasReady, { once: true });
722
- setTimeout(startDeferredAfterMindCanvasReady, 20000);
723
- } else {
724
- loadDeferredScriptsNow();
725
- }
726
- }
727
-
728
- // Start loading
729
- loadDependentScripts().catch(e => {
730
- console.error('[Script Loader] Failed:', e);
731
- window.showBlazorBootError('The page could not finish loading. Reload and try again.');
732
- });
733
- </script>
734
- <!-- ??좎뜦堉??[Upgrade] ??좎뜦堉??-->
735
- </body>
736
-
737
- </html>
738
-
739
-
740
-
741
-
742
-
743
-
744
-
745
-
668
+
669
+ console.log('[Script Loader] Critical scripts loaded, starting Blazor...');
670
+ window.mindExecutionStartupTiming?.mark('critical-scripts-loaded', {
671
+ criticalCount: criticalScripts.length + routeCriticalScripts.length
672
+ });
673
+
674
+ // SW cleanup
675
+ try {
676
+ if (window.__swCleanup) {
677
+ const cleaned = await window.__swCleanup;
678
+ const flag = '__swCleanedOnce';
679
+ if (cleaned && !sessionStorage.getItem(flag)) {
680
+ sessionStorage.setItem(flag, '1');
681
+ location.reload();
682
+ return;
683
+ }
684
+ }
685
+ } catch { }
686
+
687
+ // Start Blazor
688
+ if (window.Blazor && Blazor.start) {
689
+ window.mindExecutionStartupTiming?.mark('blazor-start', { marketingToolHost: false });
690
+ await Blazor.start();
691
+ }
692
+
693
+ const scheduleDeferredScripts = window.requestIdleCallback
694
+ ? ((callback) => window.requestIdleCallback(callback, { timeout: 1500 }))
695
+ : ((callback) => setTimeout(callback, 0));
696
+
697
+ const loadDeferredScriptsNow = () => {
698
+ scheduleDeferredScripts(() => {
699
+ (async () => {
700
+ await loadScriptBatchOrdered(
701
+ deferredScripts,
702
+ scriptUrl,
703
+ flushQueuedAgentSettings
704
+ );
705
+ console.log('[Script Loader] Deferred scripts loaded.');
706
+ window.mindExecutionStartupTiming?.mark('deferred-scripts-loaded', {
707
+ deferredCount: deferredScripts.length
708
+ });
709
+ })().catch(e => console.error('[Script Loader] Deferred load failed:', e));
710
+ });
711
+ };
712
+
713
+ if (routePath === '/mindcanvas' && deferredScripts.length > 0) {
714
+ let deferredStarted = false;
715
+ const startDeferredAfterMindCanvasReady = () => {
716
+ if (deferredStarted) return;
717
+ deferredStarted = true;
718
+ loadDeferredScriptsNow();
719
+ };
720
+
721
+ window.addEventListener('startup-timing:mindcanvas-ready', startDeferredAfterMindCanvasReady, { once: true });
722
+ setTimeout(startDeferredAfterMindCanvasReady, 20000);
723
+ } else {
724
+ loadDeferredScriptsNow();
725
+ }
726
+ }
727
+
728
+ // Start loading
729
+ loadDependentScripts().catch(e => {
730
+ console.error('[Script Loader] Failed:', e);
731
+ window.showBlazorBootError('The page could not finish loading. Reload and try again.');
732
+ });
733
+ </script>
734
+ <!-- ??좎뜦堉??[Upgrade] ??좎뜦堉??-->
735
+ </body>
736
+
737
+ </html>
738
+
739
+
740
+
741
+
742
+
743
+
744
+
745
+