@mindexec/cli 0.2.478 → 0.2.480

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