@mindexec/cli 0.2.483 → 0.2.494
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/codex-runtime.js +6 -2
- package/electron/main.cjs +56 -32
- package/electron/preload.cjs +178 -0
- package/electron/source-smoke.mjs +14 -1
- package/electron/windows-package-smoke.mjs +16 -0
- package/package.json +11 -10
- package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
- package/wwwroot/_content/MindExecution.Shared/css/app.css +1 -1
- package/wwwroot/_content/MindExecution.Shared/js/canvas-chat-task-switch.js +122 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +161 -16
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +68 -2
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js +44 -8
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +823 -111
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-native-core-bridge.js +399 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-node-search-worker.js +53 -10
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-visibility-worker.js +71 -11
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-core-simd.js +18 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-core-simd.wasm +0 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-core.js +18 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-core.wasm +0 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-native-core-adapter.js +566 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/mindexec-native-core-worker.js +89 -0
- package/wwwroot/_content/MindExecution.Shared/native-core/native-core-manifest.json +59 -0
- package/wwwroot/_framework/BenchmarkUtils.ytz7pn9azy.dll +0 -0
- package/wwwroot/_framework/Edgar.9yqq548b45.dll +0 -0
- package/wwwroot/_framework/GraphPlanarityTesting.lgk3vd0bh9.dll +0 -0
- package/wwwroot/_framework/Microsoft.Win32.SystemEvents.f8qhom7uq5.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Core.zs4n1f9hjc.dll → MindExecution.Core.tre9kny2uo.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.l9idvg7mp7.dll → MindExecution.Kernel.lvfnhwdksf.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.l37qx5d8zi.dll → MindExecution.Plugins.Admin.k2vbe4lt64.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.d7b282yazn.dll → MindExecution.Plugins.Business.u7i3r45xp5.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.iw98n0qz5k.dll → MindExecution.Plugins.Concept.7eoasvev17.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.cqgn6pa8di.dll → MindExecution.Plugins.Directory.rhh13u0z6c.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.j8xoa8nl57.dll → MindExecution.Plugins.PlanMaster.xzl2x2cqk4.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.zvpzk7om4z.dll → MindExecution.Plugins.YouTube.945tf0zc9m.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Shared.ovot7q606x.dll → MindExecution.Shared.e0w408b0ti.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Web.bzuaz35jv0.dll → MindExecution.Web.vc6ux7xjcw.dll} +0 -0
- package/wwwroot/_framework/RangeTree.iw8h1x5u2y.dll +0 -0
- package/wwwroot/_framework/System.Collections.Concurrent.jzwteolu29.dll +0 -0
- package/wwwroot/_framework/System.Collections.NonGeneric.uqtvwssxuq.dll +0 -0
- package/wwwroot/_framework/System.Collections.Specialized.85qtrfslgb.dll +0 -0
- package/wwwroot/_framework/System.Collections.xmhu72xgrp.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.Primitives.excbd02v5j.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.TypeConverter.ek2jcwibb9.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.wfe9zz2icv.dll +0 -0
- package/wwwroot/_framework/System.Console.5j283so6ps.dll +0 -0
- package/wwwroot/_framework/System.Drawing.Common.xzizafq144.dll +0 -0
- package/wwwroot/_framework/System.Private.CoreLib.7ouudb2fbl.dll +0 -0
- package/wwwroot/_framework/{System.Text.RegularExpressions.cvkox11l6l.dll → System.Text.RegularExpressions.b0vqxbob08.dll} +0 -0
- package/wwwroot/_framework/System.Threading.Tasks.Parallel.9tqazg1b0u.dll +0 -0
- package/wwwroot/_framework/System.Threading.Tasks.zl4yo3otxa.dll +0 -0
- package/wwwroot/_framework/YamlDotNet.dtey92juka.dll +0 -0
- package/wwwroot/_framework/blazor.boot.json +63 -45
- package/wwwroot/_framework/{dotnet.native.60hhmnxyoo.wasm → dotnet.native.58bvs6q392.wasm} +0 -0
- package/wwwroot/_framework/netstandard.he3m3p1s9q.dll +0 -0
- package/wwwroot/index.html +2 -1
- package/wwwroot/service-worker-assets.js +128 -56
- package/wwwroot/service-worker.js +1 -1
- package/wwwroot/_framework/System.Collections.3iuoxbe8my.dll +0 -0
- package/wwwroot/_framework/System.Collections.Concurrent.vow3rm1dku.dll +0 -0
- package/wwwroot/_framework/System.Collections.NonGeneric.npjkaz40oc.dll +0 -0
- package/wwwroot/_framework/System.Collections.Specialized.ugkjbs6p02.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.Primitives.end4v0xe2c.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.TypeConverter.tgtp5sm4iv.dll +0 -0
- package/wwwroot/_framework/System.ComponentModel.wupoltkk1t.dll +0 -0
- package/wwwroot/_framework/System.Console.9dik0wogo2.dll +0 -0
- package/wwwroot/_framework/System.Private.CoreLib.7s8wte759y.dll +0 -0
- package/wwwroot/_framework/netstandard.b50t77veor.dll +0 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const BUILD_ID = '20260830-native-core-primary-v006';
|
|
5
|
+
const STORAGE_KEY = 'mindmap.nativeCore.mode';
|
|
6
|
+
const NATIVE_WORKER_URL = `_content/MindExecution.Shared/native-core/mindexec-native-core-worker.js?v=${BUILD_ID}`;
|
|
7
|
+
const VALID_MODES = new Set(['off', 'compare', 'native']);
|
|
8
|
+
const RESULT_TYPES = new Set(['VISIBILITY_RESULT', 'HIT_TEST_RESULT', 'SELECTION_QUERY_RESULT']);
|
|
9
|
+
const MIRRORED_TYPES = new Set([
|
|
10
|
+
'RESET_BOARD',
|
|
11
|
+
'REBUILD_BOARD',
|
|
12
|
+
'UPSERT_NODE',
|
|
13
|
+
'REMOVE_NODE',
|
|
14
|
+
'VISIBILITY_QUERY',
|
|
15
|
+
'HIT_TEST_QUERY',
|
|
16
|
+
'SELECTION_QUERY'
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
function resolveMode() {
|
|
20
|
+
try {
|
|
21
|
+
const queryMode = new URLSearchParams(window.location?.search || '').get('nativeCore');
|
|
22
|
+
if (VALID_MODES.has(String(queryMode || '').toLowerCase())) {
|
|
23
|
+
return String(queryMode).toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
} catch { }
|
|
26
|
+
try {
|
|
27
|
+
const saved = String(window.localStorage?.getItem(STORAGE_KEY) || '').toLowerCase();
|
|
28
|
+
if (VALID_MODES.has(saved)) return saved;
|
|
29
|
+
} catch { }
|
|
30
|
+
return 'off';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const mode = resolveMode();
|
|
34
|
+
const status = {
|
|
35
|
+
mode,
|
|
36
|
+
ready: false,
|
|
37
|
+
backend: '',
|
|
38
|
+
activeBackend: mode === 'off' ? 'off' : '',
|
|
39
|
+
fallbackActive: false,
|
|
40
|
+
fallbackCount: 0,
|
|
41
|
+
fallbackReason: '',
|
|
42
|
+
primaryResults: 0,
|
|
43
|
+
lastPrimaryResultType: '',
|
|
44
|
+
lastPrimaryDurationMs: 0,
|
|
45
|
+
lastPrimaryRoundTripMs: 0,
|
|
46
|
+
comparisons: 0,
|
|
47
|
+
mismatches: 0,
|
|
48
|
+
lastComparison: null,
|
|
49
|
+
lastError: '',
|
|
50
|
+
buildId: BUILD_ID
|
|
51
|
+
};
|
|
52
|
+
window.__mindExecutionNativeCoreStatus = status;
|
|
53
|
+
|
|
54
|
+
function publishRuntimeStatus() {
|
|
55
|
+
const root = document.documentElement;
|
|
56
|
+
if (!root) return;
|
|
57
|
+
root.dataset.mindexecNativeCoreMode = status.mode;
|
|
58
|
+
root.dataset.mindexecNativeCoreReady = status.ready ? 'true' : 'false';
|
|
59
|
+
root.dataset.mindexecNativeCoreBackend = status.backend || '';
|
|
60
|
+
root.dataset.mindexecNativeCoreActiveBackend = status.activeBackend || '';
|
|
61
|
+
root.dataset.mindexecNativeCoreFallback = status.fallbackActive ? 'true' : 'false';
|
|
62
|
+
root.dataset.mindexecNativeCoreError = status.lastError || '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
publishRuntimeStatus();
|
|
66
|
+
|
|
67
|
+
function normalizeToken(value) {
|
|
68
|
+
const number = Number(value || 0);
|
|
69
|
+
return Number.isFinite(number) && number >= 0 ? Math.floor(number) : 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function resultKey(payload) {
|
|
73
|
+
return [
|
|
74
|
+
String(payload?.type || ''),
|
|
75
|
+
String(payload?.boardId || '').trim(),
|
|
76
|
+
normalizeToken(payload?.engineGeneration),
|
|
77
|
+
normalizeToken(payload?.boardEpoch),
|
|
78
|
+
normalizeToken(payload?.boardRevision),
|
|
79
|
+
normalizeToken(payload?.seq)
|
|
80
|
+
].join(':');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function normalizeIds(source) {
|
|
84
|
+
if (!Array.isArray(source)) return null;
|
|
85
|
+
return source
|
|
86
|
+
.map((value) => String(value || '').trim())
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.sort();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function arraysEqual(left, right) {
|
|
92
|
+
if (left === null || right === null) return left === right;
|
|
93
|
+
if (left.length !== right.length) return false;
|
|
94
|
+
for (let index = 0; index < left.length; index++) {
|
|
95
|
+
if (left[index] !== right[index]) return false;
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function numbersEqual(left, right, tolerance = 0.000001) {
|
|
101
|
+
const leftNumber = Number(left);
|
|
102
|
+
const rightNumber = Number(right);
|
|
103
|
+
if (!Number.isFinite(leftNumber) || !Number.isFinite(rightNumber)) {
|
|
104
|
+
return leftNumber === rightNumber;
|
|
105
|
+
}
|
|
106
|
+
return Math.abs(leftNumber - rightNumber) <= tolerance;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function viewportRectsEqual(left, right) {
|
|
110
|
+
if (!left || !right) return left === right;
|
|
111
|
+
return numbersEqual(left.left, right.left) &&
|
|
112
|
+
numbersEqual(left.right, right.right) &&
|
|
113
|
+
numbersEqual(left.bottom, right.bottom) &&
|
|
114
|
+
numbersEqual(left.top, right.top) &&
|
|
115
|
+
String(left.mode || '') === String(right.mode || '') &&
|
|
116
|
+
numbersEqual(left.cameraZ, right.cameraZ);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function comparePayloads(primary, native) {
|
|
120
|
+
const type = String(primary?.type || '');
|
|
121
|
+
const details = { type, seq: normalizeToken(primary?.seq), differences: [] };
|
|
122
|
+
if (primary?.stale === true || native?.stale === true) {
|
|
123
|
+
if (primary?.stale !== native?.stale) details.differences.push('stale');
|
|
124
|
+
return details;
|
|
125
|
+
}
|
|
126
|
+
if (type === 'VISIBILITY_RESULT') {
|
|
127
|
+
if (Number(primary.visibleCount) !== Number(native.visibleCount)) details.differences.push('visibleCount');
|
|
128
|
+
if (primary.visibilityChanged !== native.visibilityChanged) details.differences.push('visibilityChanged');
|
|
129
|
+
if (primary.fullResVisibilityReconcilePending !== native.fullResVisibilityReconcilePending) {
|
|
130
|
+
details.differences.push('fullResVisibilityReconcilePending');
|
|
131
|
+
}
|
|
132
|
+
if (Number(primary.lastVisibilityNodeCount) !== Number(native.lastVisibilityNodeCount)) {
|
|
133
|
+
details.differences.push('lastVisibilityNodeCount');
|
|
134
|
+
}
|
|
135
|
+
if (!viewportRectsEqual(primary.viewportRect, native.viewportRect)) details.differences.push('viewportRect');
|
|
136
|
+
if (!arraysEqual(normalizeIds(primary.enteredIds), normalizeIds(native.enteredIds))) details.differences.push('enteredIds');
|
|
137
|
+
if (!arraysEqual(normalizeIds(primary.exitedIds), normalizeIds(native.exitedIds))) details.differences.push('exitedIds');
|
|
138
|
+
const primaryHasVisibleIds = Array.isArray(primary.visibleIds);
|
|
139
|
+
const nativeHasVisibleIds = Array.isArray(native.visibleIds);
|
|
140
|
+
if (primaryHasVisibleIds !== nativeHasVisibleIds) details.differences.push('visibleIdsPresence');
|
|
141
|
+
else if (primaryHasVisibleIds && !arraysEqual(normalizeIds(primary.visibleIds), normalizeIds(native.visibleIds))) {
|
|
142
|
+
details.differences.push('visibleIds');
|
|
143
|
+
}
|
|
144
|
+
const primaryHasPriorityIds = Array.isArray(primary.priorityIds);
|
|
145
|
+
const nativeHasPriorityIds = Array.isArray(native.priorityIds);
|
|
146
|
+
if (primaryHasPriorityIds !== nativeHasPriorityIds) details.differences.push('priorityIdsPresence');
|
|
147
|
+
else if (primaryHasPriorityIds) {
|
|
148
|
+
const primaryOrder = primary.priorityIds.map((value) => String(value || '').trim()).filter(Boolean);
|
|
149
|
+
const nativeOrder = native.priorityIds.map((value) => String(value || '').trim()).filter(Boolean);
|
|
150
|
+
if (!arraysEqual(primaryOrder, nativeOrder)) details.differences.push('priorityOrder');
|
|
151
|
+
}
|
|
152
|
+
} else if (type === 'HIT_TEST_RESULT') {
|
|
153
|
+
if (!arraysEqual(normalizeIds(primary.candidateIds), normalizeIds(native.candidateIds))) {
|
|
154
|
+
details.differences.push('candidateIds');
|
|
155
|
+
}
|
|
156
|
+
} else if (type === 'SELECTION_QUERY_RESULT') {
|
|
157
|
+
if (!arraysEqual(normalizeIds(primary.selectedIds), normalizeIds(native.selectedIds))) {
|
|
158
|
+
details.differences.push('selectedIds');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return details;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function recordComparison(primary, native) {
|
|
165
|
+
const comparison = comparePayloads(primary, native);
|
|
166
|
+
comparison.matched = comparison.differences.length === 0;
|
|
167
|
+
comparison.primaryDurationMs = Number(primary?.profile?.durationMs || 0);
|
|
168
|
+
comparison.nativeDurationMs = Number(native?.profile?.durationMs || 0);
|
|
169
|
+
status.comparisons++;
|
|
170
|
+
if (!comparison.matched) status.mismatches++;
|
|
171
|
+
status.lastComparison = comparison;
|
|
172
|
+
window.MindCanvasTrace?.emit?.('nativeCore.compare', comparison);
|
|
173
|
+
if (!comparison.matched && status.mismatches <= 5) {
|
|
174
|
+
console.warn('[MindExecutionNativeCore] C++ shadow result differs from JS.', comparison);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
class NativeCoreShadow {
|
|
179
|
+
constructor() {
|
|
180
|
+
this.primaryResults = new Map();
|
|
181
|
+
this.nativeResults = new Map();
|
|
182
|
+
this.worker = null;
|
|
183
|
+
try {
|
|
184
|
+
this.worker = new Worker(NATIVE_WORKER_URL);
|
|
185
|
+
this.worker.onmessage = (event) => this._onMessage(event?.data || null);
|
|
186
|
+
this.worker.onerror = (error) => {
|
|
187
|
+
this._disable(String(error?.message || 'native core worker error'));
|
|
188
|
+
};
|
|
189
|
+
} catch (error) {
|
|
190
|
+
status.lastError = String(error?.message || error || 'native core worker creation failed');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
_onMessage(data) {
|
|
195
|
+
if (!data || typeof data !== 'object') return;
|
|
196
|
+
if (data.type === 'READY') {
|
|
197
|
+
status.ready = true;
|
|
198
|
+
status.backend = String(data.backend || 'wasm');
|
|
199
|
+
status.activeBackend = status.backend;
|
|
200
|
+
status.fallbackActive = false;
|
|
201
|
+
status.fallbackReason = '';
|
|
202
|
+
status.lastError = '';
|
|
203
|
+
publishRuntimeStatus();
|
|
204
|
+
window.MindCanvasTrace?.emit?.('nativeCore.ready', {
|
|
205
|
+
mode,
|
|
206
|
+
backend: status.backend,
|
|
207
|
+
apiVersion: Number(data.apiVersion || 0),
|
|
208
|
+
buildId: String(data.buildId || '')
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (data.type === 'NATIVE_CORE_INIT_ERROR' || data.type === 'NATIVE_CORE_RUNTIME_ERROR') {
|
|
213
|
+
this._disable(String(data.message || data.type));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (!RESULT_TYPES.has(String(data.type || ''))) return;
|
|
217
|
+
const key = resultKey(data);
|
|
218
|
+
this.nativeResults.set(key, data);
|
|
219
|
+
this._compareIfReady(key);
|
|
220
|
+
this._trim();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
_disable(message) {
|
|
224
|
+
status.lastError = String(message || 'native core disabled');
|
|
225
|
+
status.ready = false;
|
|
226
|
+
status.backend = '';
|
|
227
|
+
status.activeBackend = '';
|
|
228
|
+
publishRuntimeStatus();
|
|
229
|
+
try { this.worker?.terminate?.(); } catch { }
|
|
230
|
+
this.worker = null;
|
|
231
|
+
this.primaryResults.clear();
|
|
232
|
+
this.nativeResults.clear();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
_compareIfReady(key) {
|
|
236
|
+
const primary = this.primaryResults.get(key);
|
|
237
|
+
const native = this.nativeResults.get(key);
|
|
238
|
+
if (!primary || !native) return;
|
|
239
|
+
this.primaryResults.delete(key);
|
|
240
|
+
this.nativeResults.delete(key);
|
|
241
|
+
recordComparison(primary, native);
|
|
242
|
+
this._trim();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
_trim() {
|
|
246
|
+
const trimMap = (map) => {
|
|
247
|
+
while (map.size > 64) map.delete(map.keys().next().value);
|
|
248
|
+
};
|
|
249
|
+
trimMap(this.primaryResults);
|
|
250
|
+
trimMap(this.nativeResults);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
post(payload) {
|
|
254
|
+
if (!this.worker || !MIRRORED_TYPES.has(String(payload?.type || ''))) return false;
|
|
255
|
+
try {
|
|
256
|
+
this.worker.postMessage(payload);
|
|
257
|
+
return true;
|
|
258
|
+
} catch (error) {
|
|
259
|
+
status.lastError = String(error?.message || error || 'native core shadow post failed');
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
observePrimaryResult(payload) {
|
|
265
|
+
if (!RESULT_TYPES.has(String(payload?.type || ''))) return;
|
|
266
|
+
const key = resultKey(payload);
|
|
267
|
+
this.primaryResults.set(key, payload);
|
|
268
|
+
this._compareIfReady(key);
|
|
269
|
+
this._trim();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
dispose() {
|
|
273
|
+
try { this.worker?.terminate?.(); } catch { }
|
|
274
|
+
this.worker = null;
|
|
275
|
+
this.primaryResults.clear();
|
|
276
|
+
this.nativeResults.clear();
|
|
277
|
+
status.ready = false;
|
|
278
|
+
status.backend = '';
|
|
279
|
+
status.activeBackend = '';
|
|
280
|
+
publishRuntimeStatus();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
window.MindMapNativeCoreBridge = Object.freeze({
|
|
285
|
+
BUILD_ID,
|
|
286
|
+
STORAGE_KEY,
|
|
287
|
+
NATIVE_WORKER_URL,
|
|
288
|
+
getMode() {
|
|
289
|
+
return mode;
|
|
290
|
+
},
|
|
291
|
+
getPrimaryWorkerUrl(defaultUrl) {
|
|
292
|
+
return mode === 'native' ? NATIVE_WORKER_URL : defaultUrl;
|
|
293
|
+
},
|
|
294
|
+
createShadow() {
|
|
295
|
+
return mode === 'compare' ? new NativeCoreShadow() : null;
|
|
296
|
+
},
|
|
297
|
+
notifyPrimaryReady(data) {
|
|
298
|
+
if (mode !== 'native') return false;
|
|
299
|
+
status.ready = true;
|
|
300
|
+
status.backend = String(data?.backend || 'wasm');
|
|
301
|
+
status.activeBackend = status.backend;
|
|
302
|
+
status.fallbackActive = false;
|
|
303
|
+
status.fallbackReason = '';
|
|
304
|
+
status.primaryResults = 0;
|
|
305
|
+
status.lastPrimaryResultType = '';
|
|
306
|
+
status.lastPrimaryDurationMs = 0;
|
|
307
|
+
status.lastPrimaryRoundTripMs = 0;
|
|
308
|
+
status.lastError = '';
|
|
309
|
+
publishRuntimeStatus();
|
|
310
|
+
window.MindCanvasTrace?.emit?.('nativeCore.primaryReady', {
|
|
311
|
+
mode,
|
|
312
|
+
backend: status.backend,
|
|
313
|
+
apiVersion: Number(data?.apiVersion || 0),
|
|
314
|
+
buildId: String(data?.buildId || '')
|
|
315
|
+
});
|
|
316
|
+
return true;
|
|
317
|
+
},
|
|
318
|
+
notifyPrimaryFallback(reason) {
|
|
319
|
+
if (mode !== 'native') return false;
|
|
320
|
+
const message = String(reason || 'native core fallback');
|
|
321
|
+
status.ready = false;
|
|
322
|
+
status.backend = '';
|
|
323
|
+
status.activeBackend = 'legacy-js';
|
|
324
|
+
status.fallbackActive = true;
|
|
325
|
+
status.fallbackCount++;
|
|
326
|
+
status.fallbackReason = message;
|
|
327
|
+
status.lastError = message;
|
|
328
|
+
publishRuntimeStatus();
|
|
329
|
+
window.MindCanvasTrace?.emit?.('nativeCore.primaryFallback', {
|
|
330
|
+
mode,
|
|
331
|
+
reason: message,
|
|
332
|
+
fallbackCount: status.fallbackCount
|
|
333
|
+
});
|
|
334
|
+
return true;
|
|
335
|
+
},
|
|
336
|
+
notifyPrimaryResultAccepted(data, roundTripMs = 0) {
|
|
337
|
+
if (mode !== 'native' || status.ready !== true || status.fallbackActive === true) return false;
|
|
338
|
+
status.primaryResults++;
|
|
339
|
+
status.lastPrimaryResultType = String(data?.type || '');
|
|
340
|
+
status.lastPrimaryDurationMs = Number(data?.profile?.durationMs || 0);
|
|
341
|
+
status.lastPrimaryRoundTripMs = Number(Math.max(0, Number(roundTripMs || 0)).toFixed(2));
|
|
342
|
+
return true;
|
|
343
|
+
},
|
|
344
|
+
notifyPrimaryDisposed(reason = 'native primary disposed') {
|
|
345
|
+
if (mode !== 'native') return false;
|
|
346
|
+
status.ready = false;
|
|
347
|
+
status.backend = '';
|
|
348
|
+
status.activeBackend = '';
|
|
349
|
+
status.fallbackActive = false;
|
|
350
|
+
status.fallbackReason = '';
|
|
351
|
+
status.primaryResults = 0;
|
|
352
|
+
status.lastPrimaryResultType = '';
|
|
353
|
+
status.lastPrimaryDurationMs = 0;
|
|
354
|
+
status.lastPrimaryRoundTripMs = 0;
|
|
355
|
+
status.lastError = '';
|
|
356
|
+
publishRuntimeStatus();
|
|
357
|
+
window.MindCanvasTrace?.emit?.('nativeCore.primaryDisposed', {
|
|
358
|
+
mode,
|
|
359
|
+
reason: String(reason || 'native primary disposed')
|
|
360
|
+
});
|
|
361
|
+
return true;
|
|
362
|
+
},
|
|
363
|
+
notifyFallbackReady() {
|
|
364
|
+
if (mode !== 'native' || status.fallbackActive !== true) return false;
|
|
365
|
+
status.activeBackend = 'legacy-js';
|
|
366
|
+
publishRuntimeStatus();
|
|
367
|
+
return true;
|
|
368
|
+
},
|
|
369
|
+
notifyFallbackUnavailable(reason) {
|
|
370
|
+
if (mode !== 'native' || status.fallbackActive !== true) return false;
|
|
371
|
+
const message = String(reason || 'legacy visibility fallback unavailable');
|
|
372
|
+
status.ready = false;
|
|
373
|
+
status.backend = '';
|
|
374
|
+
status.activeBackend = 'main-thread-js';
|
|
375
|
+
status.fallbackReason = `${status.fallbackReason || 'native core fallback'}; ${message}`;
|
|
376
|
+
status.lastError = message;
|
|
377
|
+
publishRuntimeStatus();
|
|
378
|
+
window.MindCanvasTrace?.emit?.('nativeCore.fallbackUnavailable', {
|
|
379
|
+
mode,
|
|
380
|
+
reason: message,
|
|
381
|
+
activeBackend: status.activeBackend
|
|
382
|
+
});
|
|
383
|
+
return true;
|
|
384
|
+
},
|
|
385
|
+
getStatus() {
|
|
386
|
+
return { ...status };
|
|
387
|
+
},
|
|
388
|
+
setMode(nextMode) {
|
|
389
|
+
const normalized = String(nextMode || '').toLowerCase();
|
|
390
|
+
if (!VALID_MODES.has(normalized)) return false;
|
|
391
|
+
try {
|
|
392
|
+
window.localStorage?.setItem(STORAGE_KEY, normalized);
|
|
393
|
+
return true;
|
|
394
|
+
} catch {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
})();
|
|
@@ -15,6 +15,9 @@ const TOKEN_REGEX = /[\p{L}\p{M}\p{N}]{2,}/gu;
|
|
|
15
15
|
function createState() {
|
|
16
16
|
return {
|
|
17
17
|
boardId: '',
|
|
18
|
+
boardEpoch: 0,
|
|
19
|
+
engineGeneration: 0,
|
|
20
|
+
boardRevision: 0,
|
|
18
21
|
documents: new Map(),
|
|
19
22
|
tokenIndex: new Map(),
|
|
20
23
|
prefixIndex: new Map(),
|
|
@@ -28,6 +31,33 @@ function normalizeBoardId(boardId) {
|
|
|
28
31
|
return String(boardId ?? '').trim();
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
function normalizeOwnerToken(value) {
|
|
35
|
+
const number = Number(value || 0);
|
|
36
|
+
return Number.isFinite(number) && number > 0 ? Math.floor(number) : 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function normalizeBoardRevision(value) {
|
|
40
|
+
const number = Number(value || 0);
|
|
41
|
+
return Number.isFinite(number) && number >= 0 ? Math.floor(number) : 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function ownerMatches(message, requireRevision = true) {
|
|
45
|
+
if (normalizeBoardId(message?.boardId) !== runtime.boardId ||
|
|
46
|
+
normalizeOwnerToken(message?.boardEpoch) !== runtime.boardEpoch ||
|
|
47
|
+
normalizeOwnerToken(message?.engineGeneration) !== runtime.engineGeneration) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return requireRevision !== true || normalizeBoardRevision(message?.boardRevision) === runtime.boardRevision;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function acceptMutationRevision(message) {
|
|
54
|
+
if (!ownerMatches(message, false)) return false;
|
|
55
|
+
const revision = normalizeBoardRevision(message?.boardRevision);
|
|
56
|
+
if (revision < runtime.boardRevision) return false;
|
|
57
|
+
runtime.boardRevision = revision;
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
31
61
|
function limitText(value, maxLength) {
|
|
32
62
|
const text = String(value ?? '');
|
|
33
63
|
if (!text) {
|
|
@@ -212,9 +242,12 @@ function addPostingMatches(index, key, candidateScores, weight) {
|
|
|
212
242
|
});
|
|
213
243
|
}
|
|
214
244
|
|
|
215
|
-
function clearState(boardId) {
|
|
245
|
+
function clearState(boardId, boardEpoch = 0, engineGeneration = 0, boardRevision = 0) {
|
|
216
246
|
runtime = createState();
|
|
217
247
|
runtime.boardId = normalizeBoardId(boardId);
|
|
248
|
+
runtime.boardEpoch = normalizeOwnerToken(boardEpoch);
|
|
249
|
+
runtime.engineGeneration = normalizeOwnerToken(engineGeneration);
|
|
250
|
+
runtime.boardRevision = normalizeBoardRevision(boardRevision);
|
|
218
251
|
}
|
|
219
252
|
|
|
220
253
|
function normalizeNodeSnapshot(node) {
|
|
@@ -303,8 +336,8 @@ function upsertNode(node) {
|
|
|
303
336
|
document.ngrams.forEach((ngram) => addPosting(runtime.ngramIndex, ngram, document.nodeId));
|
|
304
337
|
}
|
|
305
338
|
|
|
306
|
-
function rebuildBoard(boardId, nodes) {
|
|
307
|
-
clearState(boardId);
|
|
339
|
+
function rebuildBoard(boardId, nodes, boardEpoch, engineGeneration, boardRevision) {
|
|
340
|
+
clearState(boardId, boardEpoch, engineGeneration, boardRevision);
|
|
308
341
|
const sourceNodes = Array.isArray(nodes) ? nodes : [];
|
|
309
342
|
for (let i = 0; i < sourceNodes.length; i++) {
|
|
310
343
|
upsertNode(sourceNodes[i]);
|
|
@@ -391,13 +424,17 @@ function calculateViewportBoost(document, camera) {
|
|
|
391
424
|
|
|
392
425
|
function handleSearchQuery(message) {
|
|
393
426
|
const boardId = normalizeBoardId(message.boardId);
|
|
394
|
-
if (!boardId ||
|
|
427
|
+
if (!boardId || !ownerMatches(message)) {
|
|
395
428
|
self.postMessage({
|
|
396
429
|
type: 'SEARCH_RESULT',
|
|
397
430
|
boardId,
|
|
431
|
+
boardEpoch: normalizeOwnerToken(message.boardEpoch),
|
|
432
|
+
engineGeneration: normalizeOwnerToken(message.engineGeneration),
|
|
433
|
+
boardRevision: normalizeBoardRevision(message.boardRevision),
|
|
398
434
|
seq: Number(message.seq || 0),
|
|
399
435
|
query: String(message.query || ''),
|
|
400
|
-
hits: []
|
|
436
|
+
hits: [],
|
|
437
|
+
stale: true
|
|
401
438
|
});
|
|
402
439
|
return;
|
|
403
440
|
}
|
|
@@ -411,6 +448,9 @@ function handleSearchQuery(message) {
|
|
|
411
448
|
self.postMessage({
|
|
412
449
|
type: 'SEARCH_RESULT',
|
|
413
450
|
boardId,
|
|
451
|
+
boardEpoch: runtime.boardEpoch,
|
|
452
|
+
engineGeneration: runtime.engineGeneration,
|
|
453
|
+
boardRevision: runtime.boardRevision,
|
|
414
454
|
seq: Number(message.seq || 0),
|
|
415
455
|
query: String(message.query || ''),
|
|
416
456
|
hits: []
|
|
@@ -494,6 +534,9 @@ function handleSearchQuery(message) {
|
|
|
494
534
|
self.postMessage({
|
|
495
535
|
type: 'SEARCH_RESULT',
|
|
496
536
|
boardId,
|
|
537
|
+
boardEpoch: runtime.boardEpoch,
|
|
538
|
+
engineGeneration: runtime.engineGeneration,
|
|
539
|
+
boardRevision: runtime.boardRevision,
|
|
497
540
|
seq: Number(message.seq || 0),
|
|
498
541
|
query: String(message.query || ''),
|
|
499
542
|
hits: ranked.slice(0, normalizedLimit),
|
|
@@ -513,23 +556,23 @@ self.onmessage = function (event) {
|
|
|
513
556
|
|
|
514
557
|
switch (message.type) {
|
|
515
558
|
case 'RESET_BOARD':
|
|
516
|
-
clearState(message.boardId);
|
|
559
|
+
clearState(message.boardId, message.boardEpoch, message.engineGeneration, message.boardRevision);
|
|
517
560
|
break;
|
|
518
561
|
case 'REBUILD_BOARD':
|
|
519
|
-
rebuildBoard(message.boardId, message.nodes);
|
|
562
|
+
rebuildBoard(message.boardId, message.nodes, message.boardEpoch, message.engineGeneration, message.boardRevision);
|
|
520
563
|
break;
|
|
521
564
|
case 'UPSERT_NODE':
|
|
522
|
-
if (
|
|
565
|
+
if (acceptMutationRevision(message)) {
|
|
523
566
|
upsertNode(message.node);
|
|
524
567
|
}
|
|
525
568
|
break;
|
|
526
569
|
case 'REMOVE_NODE':
|
|
527
|
-
if (
|
|
570
|
+
if (acceptMutationRevision(message)) {
|
|
528
571
|
removeDocument(String(message.nodeId || '').trim());
|
|
529
572
|
}
|
|
530
573
|
break;
|
|
531
574
|
case 'BATCH_SYNC':
|
|
532
|
-
if (
|
|
575
|
+
if (ownerMatches(message)) {
|
|
533
576
|
const removedIds = Array.isArray(message.removedIds) ? message.removedIds : [];
|
|
534
577
|
for (let i = 0; i < removedIds.length; i++) {
|
|
535
578
|
removeDocument(String(removedIds[i] || '').trim());
|