@atlaskit/editor-plugin-autocomplete 3.4.1 → 3.6.0
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/CHANGELOG.md +26 -0
- package/dist/cjs/pm-plugins/autocomplete-plugin.js +44 -5
- package/dist/cjs/pm-plugins/debug-mode.js +48 -7
- package/dist/cjs/pm-plugins/local-slow-lane-client.js +239 -63
- package/dist/es2019/pm-plugins/autocomplete-plugin.js +46 -5
- package/dist/es2019/pm-plugins/debug-mode.js +46 -7
- package/dist/es2019/pm-plugins/local-slow-lane-client.js +139 -11
- package/dist/esm/pm-plugins/autocomplete-plugin.js +44 -5
- package/dist/esm/pm-plugins/debug-mode.js +48 -7
- package/dist/esm/pm-plugins/local-slow-lane-client.js +238 -62
- package/dist/types/pm-plugins/debug-mode.d.ts +19 -4
- package/dist/types/pm-plugins/local-slow-lane-client.d.ts +52 -0
- package/dist/types-ts4.5/pm-plugins/debug-mode.d.ts +19 -4
- package/dist/types-ts4.5/pm-plugins/local-slow-lane-client.d.ts +52 -0
- package/package.json +2 -2
- package/src/pm-plugins/autocomplete-plugin.ts +45 -1
- package/src/pm-plugins/debug-mode.ts +53 -6
- package/src/pm-plugins/local-slow-lane-client.ts +223 -12
|
@@ -16,7 +16,12 @@ import type { AutocompletePlugin } from '../autocompletePluginType';
|
|
|
16
16
|
|
|
17
17
|
import { isAutocompleteDebugEnabled } from './debug-mode';
|
|
18
18
|
import { createGhostTextDecorationSet } from './ghost-text-decoration';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
createLocalSlowLaneClient,
|
|
21
|
+
type LocalSlowLaneClient,
|
|
22
|
+
type LocalSlowLaneLoadError,
|
|
23
|
+
type LocalSlowLaneLoadSuccess,
|
|
24
|
+
} from './local-slow-lane-client';
|
|
20
25
|
import { createSlowLaneClient, setDefaultSlowLaneClient, isWordBoundary } from './slow-lane-client';
|
|
21
26
|
import {
|
|
22
27
|
predict,
|
|
@@ -298,6 +303,43 @@ export const createAutocompletePlugin = (
|
|
|
298
303
|
});
|
|
299
304
|
};
|
|
300
305
|
|
|
306
|
+
const fireLocalModelLoadedAnalytics = (info: LocalSlowLaneLoadSuccess): void => {
|
|
307
|
+
api?.analytics?.actions.fireAnalyticsEvent({
|
|
308
|
+
action: ACTION.LOCAL_MODEL_LOADED,
|
|
309
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
310
|
+
eventType: EVENT_TYPE.TRACK,
|
|
311
|
+
attributes: {
|
|
312
|
+
modelId: info.modelId,
|
|
313
|
+
embeddingModelId: info.embeddingModelId,
|
|
314
|
+
loadDurationMs: info.loadDurationMs,
|
|
315
|
+
gpuVendor: info.capabilities.vendor,
|
|
316
|
+
gpuArchitecture: info.capabilities.architecture,
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const fireLocalModelLoadFailedAnalytics = (error: LocalSlowLaneLoadError): void => {
|
|
322
|
+
const { capabilities } = error;
|
|
323
|
+
api?.analytics?.actions.fireAnalyticsEvent({
|
|
324
|
+
action: ACTION.LOCAL_MODEL_LOAD_FAILED,
|
|
325
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
326
|
+
eventType: EVENT_TYPE.TRACK,
|
|
327
|
+
attributes: {
|
|
328
|
+
reason: error.reason,
|
|
329
|
+
message: error.message,
|
|
330
|
+
modelId: error.modelId,
|
|
331
|
+
embeddingModelId: error.embeddingModelId,
|
|
332
|
+
webgpuAvailable: capabilities.available,
|
|
333
|
+
adapterAvailable: capabilities.adapterAvailable,
|
|
334
|
+
shaderF16Supported: capabilities.shaderF16Supported,
|
|
335
|
+
maxBufferSizeMB: capabilities.maxBufferSizeMB,
|
|
336
|
+
maxStorageBufferBindingSizeMB: capabilities.maxStorageBufferBindingSizeMB,
|
|
337
|
+
gpuVendor: capabilities.vendor,
|
|
338
|
+
gpuArchitecture: capabilities.architecture,
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
|
|
301
343
|
const fireSuggestionInsertedAnalytics = (ghostText: string): void => {
|
|
302
344
|
const typedLength = lastSuggestionTypedLength;
|
|
303
345
|
const suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
|
|
@@ -319,6 +361,8 @@ export const createAutocompletePlugin = (
|
|
|
319
361
|
const slowLaneClient = options?.useLocalModel
|
|
320
362
|
? createLocalSlowLaneClient({
|
|
321
363
|
debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS,
|
|
364
|
+
onLoadSuccess: fireLocalModelLoadedAnalytics,
|
|
365
|
+
onLoadError: fireLocalModelLoadFailedAnalytics,
|
|
322
366
|
})
|
|
323
367
|
: createSlowLaneClient({
|
|
324
368
|
baseUrl: '',
|
|
@@ -1,18 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Contextual Typeahead Completions (CTC) debug logging utility.
|
|
3
3
|
*
|
|
4
|
-
* Logs are silent by default.
|
|
4
|
+
* Logs are silent by default. Enable in any environment (dev, staging, prod):
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* // Live, for the current session (no reload required):
|
|
7
|
+
* __atlCtcDebug__.enable()
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
+
* // To disable:
|
|
10
|
+
* __atlCtcDebug__.disable()
|
|
9
11
|
*
|
|
10
|
-
*
|
|
12
|
+
* // From initial page load (survives reload) — append to the URL:
|
|
13
|
+
* ?atlCtcDebug=1
|
|
14
|
+
*
|
|
15
|
+
* Storage-free by design: avoids browser-storage consent controls (BSC), which can
|
|
16
|
+
* block uncategorized localStorage/sessionStorage/cookie writes in some products.
|
|
11
17
|
*/
|
|
12
|
-
|
|
18
|
+
|
|
19
|
+
declare global {
|
|
20
|
+
interface Window {
|
|
21
|
+
__atlCtcDebug__?: {
|
|
22
|
+
enable: () => void;
|
|
23
|
+
disable: () => void;
|
|
24
|
+
isEnabled: () => boolean;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const hasUrlDebugFlag = (): boolean => {
|
|
30
|
+
if (typeof window === 'undefined') {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
13
33
|
try {
|
|
14
|
-
return
|
|
34
|
+
return new URLSearchParams(window.location.search).get('atlCtcDebug') === '1';
|
|
15
35
|
} catch {
|
|
16
36
|
return false;
|
|
17
37
|
}
|
|
18
38
|
};
|
|
39
|
+
|
|
40
|
+
// State lives on the window object (not a module closure) so duplicate copies of this
|
|
41
|
+
// module across separate bundles/realms share one source of truth and the console API
|
|
42
|
+
// controls them all. In-memory only; persisted across reload via the URL flag.
|
|
43
|
+
const getDebugApi = (): Window['__atlCtcDebug__'] => {
|
|
44
|
+
if (typeof window === 'undefined') {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (!window.__atlCtcDebug__) {
|
|
48
|
+
let debugEnabled = hasUrlDebugFlag();
|
|
49
|
+
window.__atlCtcDebug__ = {
|
|
50
|
+
enable: () => {
|
|
51
|
+
debugEnabled = true;
|
|
52
|
+
},
|
|
53
|
+
disable: () => {
|
|
54
|
+
debugEnabled = false;
|
|
55
|
+
},
|
|
56
|
+
isEnabled: () => debugEnabled,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return window.__atlCtcDebug__;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const isAutocompleteDebugEnabled = (): boolean => getDebugApi()?.isEnabled() ?? false;
|
|
63
|
+
|
|
64
|
+
// Eagerly install so the console API is available on load, regardless of call order.
|
|
65
|
+
getDebugApi();
|
|
@@ -71,6 +71,10 @@ export interface LocalSlowLaneClientConfig {
|
|
|
71
71
|
* `customModelConfig` with the model URL and WASM library URL.
|
|
72
72
|
*/
|
|
73
73
|
modelId?: string;
|
|
74
|
+
/** Callback fired when the engine fails to load/start. */
|
|
75
|
+
onLoadError?: (error: LocalSlowLaneLoadError) => void;
|
|
76
|
+
/** Callback fired when the engine successfully loads and is ready. */
|
|
77
|
+
onLoadSuccess?: (info: LocalSlowLaneLoadSuccess) => void;
|
|
74
78
|
/** Callback fired with status messages (model loading progress, etc.). */
|
|
75
79
|
onStatus?: (message: string) => void;
|
|
76
80
|
/** Callback fired when inference returns new results. */
|
|
@@ -91,6 +95,80 @@ export interface LocalSlowLaneClient {
|
|
|
91
95
|
updateContext: (text: string) => void;
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Why the local engine failed to load/start.
|
|
100
|
+
*
|
|
101
|
+
* The first three are user-machine limitations (WebGPU missing, no compatible
|
|
102
|
+
* GPU adapter, GPU lacks the `shader-f16` feature the model needs);
|
|
103
|
+
* `insufficient_memory` is hit when weights don't fit in VRAM. The rest cover
|
|
104
|
+
* delivery/runtime failures unrelated to hardware.
|
|
105
|
+
*/
|
|
106
|
+
export type LocalSlowLaneLoadErrorReason =
|
|
107
|
+
| 'webgpu_unavailable'
|
|
108
|
+
| 'webgpu_no_adapter'
|
|
109
|
+
| 'missing_shader_f16'
|
|
110
|
+
| 'insufficient_memory'
|
|
111
|
+
| 'model_download_failed'
|
|
112
|
+
| 'module_load_failed'
|
|
113
|
+
| 'init_failed';
|
|
114
|
+
|
|
115
|
+
/** Snapshot of the machine's WebGPU support, used to explain hardware limits. */
|
|
116
|
+
export interface WebGpuCapabilities {
|
|
117
|
+
/** GPU architecture reported by the adapter (e.g. "metal-3", "rdna2"). */
|
|
118
|
+
architecture?: string;
|
|
119
|
+
/** Whether `navigator.gpu.requestAdapter()` returned a usable adapter. */
|
|
120
|
+
adapterAvailable?: boolean;
|
|
121
|
+
/** Whether `navigator.gpu` exists at all. */
|
|
122
|
+
available: boolean;
|
|
123
|
+
/** Largest single GPU buffer the adapter allows, in MB. */
|
|
124
|
+
maxBufferSizeMB?: number;
|
|
125
|
+
/** Largest storage-buffer binding the adapter allows, in MB. */
|
|
126
|
+
maxStorageBufferBindingSizeMB?: number;
|
|
127
|
+
/** Whether the adapter exposes the `shader-f16` feature the model requires. */
|
|
128
|
+
shaderF16Supported?: boolean;
|
|
129
|
+
/** GPU vendor reported by the adapter (e.g. "apple", "intel"). */
|
|
130
|
+
vendor?: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface LocalSlowLaneLoadError {
|
|
134
|
+
/** WebGPU support snapshot — explains hardware limitations behind the failure. */
|
|
135
|
+
capabilities: WebGpuCapabilities;
|
|
136
|
+
/** Semantic embedder loaded alongside the causal LM (loads atomically). */
|
|
137
|
+
embeddingModelId: string;
|
|
138
|
+
/** Canonical, controlled failure description (never raw error text). */
|
|
139
|
+
message: string;
|
|
140
|
+
/** Causal LM identifier that failed to load. */
|
|
141
|
+
modelId: string;
|
|
142
|
+
/** Coarse, privacy-safe failure category. */
|
|
143
|
+
reason: LocalSlowLaneLoadErrorReason;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface LocalSlowLaneLoadSuccess {
|
|
147
|
+
/** WebGPU support snapshot for the machine that loaded the model. */
|
|
148
|
+
capabilities: WebGpuCapabilities;
|
|
149
|
+
/** Semantic embedder loaded alongside the causal LM (loads atomically). */
|
|
150
|
+
embeddingModelId: string;
|
|
151
|
+
/** Model engine load time in ms (excludes the WebGPU capability probe). */
|
|
152
|
+
loadDurationMs: number;
|
|
153
|
+
/** Causal LM identifier that loaded. */
|
|
154
|
+
modelId: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Minimal WebGPU shape: lib.dom types aren't guaranteed in this build target.
|
|
158
|
+
interface MinimalGpuAdapterInfo {
|
|
159
|
+
architecture?: string;
|
|
160
|
+
vendor?: string;
|
|
161
|
+
}
|
|
162
|
+
interface MinimalGpuAdapter {
|
|
163
|
+
features: { has: (feature: string) => boolean };
|
|
164
|
+
info?: MinimalGpuAdapterInfo;
|
|
165
|
+
limits?: { maxBufferSize?: number; maxStorageBufferBindingSize?: number };
|
|
166
|
+
requestAdapterInfo?: () => Promise<MinimalGpuAdapterInfo>;
|
|
167
|
+
}
|
|
168
|
+
interface MinimalGpu {
|
|
169
|
+
requestAdapter: () => Promise<MinimalGpuAdapter | null>;
|
|
170
|
+
}
|
|
171
|
+
|
|
94
172
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
95
173
|
|
|
96
174
|
const DEFAULT_DEBOUNCE_MS = 300;
|
|
@@ -584,6 +662,8 @@ export const createLocalSlowLaneClient = (
|
|
|
584
662
|
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
585
663
|
onUpdate,
|
|
586
664
|
onStatus,
|
|
665
|
+
onLoadError,
|
|
666
|
+
onLoadSuccess,
|
|
587
667
|
modelId = LOCAL_MLC_CAUSAL_MODEL_ID,
|
|
588
668
|
customModelConfig,
|
|
589
669
|
} = config;
|
|
@@ -641,7 +721,142 @@ export const createLocalSlowLaneClient = (
|
|
|
641
721
|
onStatus?.(message);
|
|
642
722
|
};
|
|
643
723
|
|
|
724
|
+
const bytesToMB = (bytes?: number): number | undefined =>
|
|
725
|
+
typeof bytes === 'number' ? Math.round(bytes / (1024 * 1024)) : undefined;
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Inspect the machine's WebGPU support so a load failure can be attributed
|
|
729
|
+
* to a concrete hardware/browser limitation rather than a generic error.
|
|
730
|
+
*/
|
|
731
|
+
const probeWebGpuCapabilities = async (): Promise<WebGpuCapabilities> => {
|
|
732
|
+
const gpu = (navigator as Navigator & { gpu?: MinimalGpu }).gpu;
|
|
733
|
+
if (!gpu) {
|
|
734
|
+
return { available: false };
|
|
735
|
+
}
|
|
736
|
+
try {
|
|
737
|
+
const adapter = await gpu.requestAdapter();
|
|
738
|
+
if (!adapter) {
|
|
739
|
+
return { available: true, adapterAvailable: false };
|
|
740
|
+
}
|
|
741
|
+
let vendor: string | undefined;
|
|
742
|
+
let architecture: string | undefined;
|
|
743
|
+
try {
|
|
744
|
+
const info = adapter.info ?? (await adapter.requestAdapterInfo?.());
|
|
745
|
+
vendor = info?.vendor || undefined;
|
|
746
|
+
architecture = info?.architecture || undefined;
|
|
747
|
+
} catch {
|
|
748
|
+
// adapter info is best-effort
|
|
749
|
+
}
|
|
750
|
+
return {
|
|
751
|
+
available: true,
|
|
752
|
+
adapterAvailable: true,
|
|
753
|
+
shaderF16Supported: adapter.features.has('shader-f16'),
|
|
754
|
+
maxBufferSizeMB: bytesToMB(adapter.limits?.maxBufferSize),
|
|
755
|
+
maxStorageBufferBindingSizeMB: bytesToMB(adapter.limits?.maxStorageBufferBindingSize),
|
|
756
|
+
vendor,
|
|
757
|
+
architecture,
|
|
758
|
+
};
|
|
759
|
+
} catch {
|
|
760
|
+
return { available: true, adapterAvailable: false };
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
/** Map an MLC/WebLLM engine-creation error message to a coarse reason. */
|
|
765
|
+
const classifyEngineError = (message: string): LocalSlowLaneLoadErrorReason => {
|
|
766
|
+
const lower = message.toLowerCase();
|
|
767
|
+
if (
|
|
768
|
+
lower.includes('loading chunk') ||
|
|
769
|
+
lower.includes('dynamically imported module') ||
|
|
770
|
+
lower.includes('dynamic import')
|
|
771
|
+
) {
|
|
772
|
+
return 'module_load_failed';
|
|
773
|
+
}
|
|
774
|
+
if (
|
|
775
|
+
lower.includes('out of memory') ||
|
|
776
|
+
/\boom\b/u.test(lower) ||
|
|
777
|
+
lower.includes('allocation') ||
|
|
778
|
+
lower.includes('exceeds') ||
|
|
779
|
+
lower.includes('buffer size') ||
|
|
780
|
+
lower.includes('not enough memory')
|
|
781
|
+
) {
|
|
782
|
+
return 'insufficient_memory';
|
|
783
|
+
}
|
|
784
|
+
// Pre-flight already returns missing_shader_f16 when the feature is absent,
|
|
785
|
+
// so only match the exact feature token here — not bare 'shader' (compile
|
|
786
|
+
// errors) or bare 'f16' (present in model ids like q0f16-MLC).
|
|
787
|
+
if (lower.includes('shader-f16') || lower.includes('shader_f16')) {
|
|
788
|
+
return 'missing_shader_f16';
|
|
789
|
+
}
|
|
790
|
+
if (
|
|
791
|
+
lower.includes('fetch') ||
|
|
792
|
+
lower.includes('network') ||
|
|
793
|
+
lower.includes('download') ||
|
|
794
|
+
lower.includes('http') ||
|
|
795
|
+
lower.includes('cache')
|
|
796
|
+
) {
|
|
797
|
+
return 'model_download_failed';
|
|
798
|
+
}
|
|
799
|
+
return 'init_failed';
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
// Canonical, controlled failure descriptions. We never emit the raw engine
|
|
803
|
+
// error into analytics — it can embed customer-context URLs/paths (HOT-120175)
|
|
804
|
+
// — so the analytics `message` is always one of these fixed strings.
|
|
805
|
+
const LOAD_FAILURE_MESSAGE: Record<LocalSlowLaneLoadErrorReason, string> = {
|
|
806
|
+
webgpu_unavailable: 'WebGPU is not available in this browser',
|
|
807
|
+
webgpu_no_adapter: 'No compatible WebGPU adapter found',
|
|
808
|
+
missing_shader_f16: 'GPU does not support the shader-f16 feature',
|
|
809
|
+
insufficient_memory: 'Insufficient GPU memory to load the model',
|
|
810
|
+
model_download_failed: 'Failed to download model assets',
|
|
811
|
+
module_load_failed: 'Failed to load the web-llm runtime module',
|
|
812
|
+
init_failed: 'Model engine failed to initialise',
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
const handleLoadFailure = (
|
|
816
|
+
reason: LocalSlowLaneLoadErrorReason,
|
|
817
|
+
capabilities: WebGpuCapabilities,
|
|
818
|
+
// Raw engine error — local debug logging only, never sent to analytics.
|
|
819
|
+
debugDetail?: string,
|
|
820
|
+
): void => {
|
|
821
|
+
ready = false;
|
|
822
|
+
const message = LOAD_FAILURE_MESSAGE[reason];
|
|
823
|
+
if (isAutocompleteDebugEnabled()) {
|
|
824
|
+
// eslint-disable-next-line no-console
|
|
825
|
+
console.log(
|
|
826
|
+
`[LocalSlowLane] Engine initialisation failed (${reason}): ${debugDetail ?? message}`,
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
onStatus?.(`Engine initialisation failed: ${message}`);
|
|
830
|
+
onLoadError?.({
|
|
831
|
+
reason,
|
|
832
|
+
message,
|
|
833
|
+
modelId,
|
|
834
|
+
embeddingModelId: LOCAL_MLC_EMBEDDING_MODEL_ID,
|
|
835
|
+
capabilities,
|
|
836
|
+
});
|
|
837
|
+
engineInitPromise = null;
|
|
838
|
+
initFailed = true;
|
|
839
|
+
};
|
|
840
|
+
|
|
644
841
|
const initEngine = async (): Promise<void> => {
|
|
842
|
+
const capabilities = await probeWebGpuCapabilities();
|
|
843
|
+
|
|
844
|
+
// ── Pre-flight: machine limitations short-circuit before the expensive load ──
|
|
845
|
+
if (!capabilities.available) {
|
|
846
|
+
handleLoadFailure('webgpu_unavailable', capabilities);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
if (capabilities.adapterAvailable === false) {
|
|
850
|
+
handleLoadFailure('webgpu_no_adapter', capabilities);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (capabilities.shaderF16Supported === false) {
|
|
854
|
+
handleLoadFailure('missing_shader_f16', capabilities);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
const startTime = performance.now();
|
|
859
|
+
|
|
645
860
|
try {
|
|
646
861
|
if (isAutocompleteDebugEnabled()) {
|
|
647
862
|
// eslint-disable-next-line no-console
|
|
@@ -653,10 +868,6 @@ export const createLocalSlowLaneClient = (
|
|
|
653
868
|
}
|
|
654
869
|
onStatus?.(`Initialising models: ${modelId} + ${LOCAL_MLC_EMBEDDING_MODEL_ID}…`);
|
|
655
870
|
|
|
656
|
-
if (!('gpu' in navigator)) {
|
|
657
|
-
throw new Error('WebGPU not supported');
|
|
658
|
-
}
|
|
659
|
-
|
|
660
871
|
// Fetch the web-llm runtime and the BE-parity lookup tables in parallel;
|
|
661
872
|
// both are dynamically imported so they stay out of the main editor chunk.
|
|
662
873
|
const [{ MLCEngine: MLCEngineCtor, prebuiltAppConfig }] = await Promise.all([
|
|
@@ -714,6 +925,7 @@ export const createLocalSlowLaneClient = (
|
|
|
714
925
|
|
|
715
926
|
engine = newEngine;
|
|
716
927
|
ready = true;
|
|
928
|
+
const loadDurationMs = Math.round(performance.now() - startTime);
|
|
717
929
|
|
|
718
930
|
if (isAutocompleteDebugEnabled()) {
|
|
719
931
|
// eslint-disable-next-line no-console
|
|
@@ -740,16 +952,15 @@ export const createLocalSlowLaneClient = (
|
|
|
740
952
|
);
|
|
741
953
|
}
|
|
742
954
|
onStatus?.('Model loaded and ready.');
|
|
955
|
+
onLoadSuccess?.({
|
|
956
|
+
modelId,
|
|
957
|
+
embeddingModelId: LOCAL_MLC_EMBEDDING_MODEL_ID,
|
|
958
|
+
loadDurationMs,
|
|
959
|
+
capabilities,
|
|
960
|
+
});
|
|
743
961
|
} catch (err) {
|
|
744
962
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
745
|
-
|
|
746
|
-
if (isAutocompleteDebugEnabled()) {
|
|
747
|
-
// eslint-disable-next-line no-console
|
|
748
|
-
console.log(`[LocalSlowLane] Engine initialisation failed: ${errorMsg}`);
|
|
749
|
-
}
|
|
750
|
-
onStatus?.(`Engine initialisation failed: ${errorMsg}`);
|
|
751
|
-
engineInitPromise = null;
|
|
752
|
-
initFailed = true;
|
|
963
|
+
handleLoadFailure(classifyEngineError(errorMsg), capabilities, errorMsg);
|
|
753
964
|
}
|
|
754
965
|
};
|
|
755
966
|
|