@atlaskit/editor-plugin-autocomplete 3.5.0 → 3.6.1
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 +25 -0
- package/dist/cjs/pm-plugins/autocomplete-plugin.js +50 -7
- package/dist/cjs/pm-plugins/local-slow-lane-client.js +241 -63
- package/dist/cjs/pm-plugins/text-predictor.js +18 -4
- package/dist/es2019/pm-plugins/autocomplete-plugin.js +52 -7
- package/dist/es2019/pm-plugins/local-slow-lane-client.js +141 -11
- package/dist/es2019/pm-plugins/text-predictor.js +17 -3
- package/dist/esm/pm-plugins/autocomplete-plugin.js +50 -7
- package/dist/esm/pm-plugins/local-slow-lane-client.js +240 -62
- package/dist/esm/pm-plugins/text-predictor.js +18 -4
- package/dist/types/pm-plugins/local-slow-lane-client.d.ts +52 -0
- package/dist/types/pm-plugins/text-predictor.d.ts +4 -1
- package/dist/types-ts4.5/pm-plugins/local-slow-lane-client.d.ts +52 -0
- package/dist/types-ts4.5/pm-plugins/text-predictor.d.ts +4 -1
- package/package.json +2 -2
- package/src/pm-plugins/autocomplete-plugin.ts +57 -10
- package/src/pm-plugins/local-slow-lane-client.ts +224 -12
- package/src/pm-plugins/text-predictor.ts +12 -6
|
@@ -733,7 +733,8 @@ var unwrapJsonModule = function unwrapJsonModule(mod, shape) {
|
|
|
733
733
|
};
|
|
734
734
|
var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
735
735
|
var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(options) {
|
|
736
|
-
var
|
|
736
|
+
var _options$isLocalLLM;
|
|
737
|
+
var isLocalLLM, url, _wordIndexOuter$index, res, buffer, float32, wordIndexModule, wordIndexOuter, wordIndex, nWords, dim, _t, _t2;
|
|
737
738
|
return _regenerator.default.wrap(function (_context) {
|
|
738
739
|
while (1) switch (_context.prev = _context.next) {
|
|
739
740
|
case 0:
|
|
@@ -751,8 +752,11 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
751
752
|
console.warn('[text-predictor] loadVectorsAsync called without a getBinaryUrl — vectors will not load. Pass getVectorsBinaryUrl via plugin options.');
|
|
752
753
|
return _context.abrupt("return");
|
|
753
754
|
case 2:
|
|
755
|
+
isLocalLLM = (_options$isLocalLLM = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM !== void 0 ? _options$isLocalLLM : false;
|
|
754
756
|
vectorsLoadStarted = true;
|
|
755
|
-
(0, _ufo.startExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton'
|
|
757
|
+
(0, _ufo.startExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
758
|
+
isLocalLLM: isLocalLLM
|
|
759
|
+
});
|
|
756
760
|
_context.prev = 3;
|
|
757
761
|
_context.next = 4;
|
|
758
762
|
return options.getBinaryUrl();
|
|
@@ -765,6 +769,7 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
765
769
|
_t = _context["catch"](3);
|
|
766
770
|
vectorsLoadStarted = false;
|
|
767
771
|
(0, _ufo.failExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
772
|
+
isLocalLLM: isLocalLLM,
|
|
768
773
|
errorType: 'resolve_url'
|
|
769
774
|
});
|
|
770
775
|
// eslint-disable-next-line no-console
|
|
@@ -782,6 +787,7 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
782
787
|
}
|
|
783
788
|
vectorsLoadStarted = false;
|
|
784
789
|
(0, _ufo.failExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
790
|
+
isLocalLLM: isLocalLLM,
|
|
785
791
|
status: res.status,
|
|
786
792
|
errorType: 'http_error'
|
|
787
793
|
});
|
|
@@ -816,6 +822,7 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
816
822
|
dim: dim
|
|
817
823
|
};
|
|
818
824
|
(0, _ufo.succeedExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
825
|
+
isLocalLLM: isLocalLLM,
|
|
819
826
|
wordCount: nWords,
|
|
820
827
|
dim: dim,
|
|
821
828
|
sizeBytes: float32.byteLength
|
|
@@ -835,6 +842,7 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
835
842
|
_t2 = _context["catch"](6);
|
|
836
843
|
vectorsLoadStarted = false;
|
|
837
844
|
(0, _ufo.failExp)(_ufo.EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
845
|
+
isLocalLLM: isLocalLLM,
|
|
838
846
|
errorType: 'network'
|
|
839
847
|
});
|
|
840
848
|
// eslint-disable-next-line no-console
|
|
@@ -853,19 +861,23 @@ var initVectors = exports.initVectors = function initVectors(store) {
|
|
|
853
861
|
vectorStore = store;
|
|
854
862
|
};
|
|
855
863
|
var vocabularyLoadPromise;
|
|
856
|
-
var loadDefaultVocabulary = exports.loadDefaultVocabulary = function loadDefaultVocabulary() {
|
|
864
|
+
var loadDefaultVocabulary = exports.loadDefaultVocabulary = function loadDefaultVocabulary(options) {
|
|
865
|
+
var _options$isLocalLLM2;
|
|
857
866
|
if (isInitialized) {
|
|
858
867
|
return Promise.resolve();
|
|
859
868
|
}
|
|
860
869
|
if (vocabularyLoadPromise) {
|
|
861
870
|
return vocabularyLoadPromise;
|
|
862
871
|
}
|
|
872
|
+
var isLocalLLM = (_options$isLocalLLM2 = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM2 !== void 0 ? _options$isLocalLLM2 : false;
|
|
863
873
|
vocabularyLoadPromise = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
864
874
|
var _yield$Promise$all, _yield$Promise$all2, vocabularyModule, l3VocabularyModule, vocabularyData, l3VocabularyData, terms, _t3;
|
|
865
875
|
return _regenerator.default.wrap(function (_context2) {
|
|
866
876
|
while (1) switch (_context2.prev = _context2.next) {
|
|
867
877
|
case 0:
|
|
868
|
-
(0, _ufo.startExp)(_ufo.EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton'
|
|
878
|
+
(0, _ufo.startExp)(_ufo.EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
879
|
+
isLocalLLM: isLocalLLM
|
|
880
|
+
});
|
|
869
881
|
_context2.prev = 1;
|
|
870
882
|
_context2.next = 2;
|
|
871
883
|
return Promise.all([Promise.resolve().then(function () {
|
|
@@ -904,6 +916,7 @@ var loadDefaultVocabulary = exports.loadDefaultVocabulary = function loadDefault
|
|
|
904
916
|
terms: terms
|
|
905
917
|
});
|
|
906
918
|
(0, _ufo.succeedExp)(_ufo.EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
919
|
+
isLocalLLM: isLocalLLM,
|
|
907
920
|
l2WordCount: terms.length,
|
|
908
921
|
l3WordCount: l3VocabularyData.length
|
|
909
922
|
});
|
|
@@ -913,6 +926,7 @@ var loadDefaultVocabulary = exports.loadDefaultVocabulary = function loadDefault
|
|
|
913
926
|
_context2.prev = 4;
|
|
914
927
|
_t3 = _context2["catch"](1);
|
|
915
928
|
(0, _ufo.failExp)(_ufo.EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
929
|
+
isLocalLLM: isLocalLLM,
|
|
916
930
|
errorType: 'parse_error'
|
|
917
931
|
});
|
|
918
932
|
// Allow a later call to retry the load rather than caching the failure.
|
|
@@ -235,12 +235,51 @@ export const createAutocompletePlugin = (options, api) => {
|
|
|
235
235
|
}
|
|
236
236
|
});
|
|
237
237
|
};
|
|
238
|
-
const
|
|
238
|
+
const fireLocalModelLoadedAnalytics = info => {
|
|
239
239
|
var _api$analytics2;
|
|
240
|
+
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent({
|
|
241
|
+
action: ACTION.LOCAL_MODEL_LOADED,
|
|
242
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
243
|
+
eventType: EVENT_TYPE.TRACK,
|
|
244
|
+
attributes: {
|
|
245
|
+
modelId: info.modelId,
|
|
246
|
+
embeddingModelId: info.embeddingModelId,
|
|
247
|
+
loadDurationMs: info.loadDurationMs,
|
|
248
|
+
gpuVendor: info.capabilities.vendor,
|
|
249
|
+
gpuArchitecture: info.capabilities.architecture
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
const fireLocalModelLoadFailedAnalytics = error => {
|
|
254
|
+
var _api$analytics3;
|
|
255
|
+
const {
|
|
256
|
+
capabilities
|
|
257
|
+
} = error;
|
|
258
|
+
api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent({
|
|
259
|
+
action: ACTION.LOCAL_MODEL_LOAD_FAILED,
|
|
260
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
261
|
+
eventType: EVENT_TYPE.TRACK,
|
|
262
|
+
attributes: {
|
|
263
|
+
reason: error.reason,
|
|
264
|
+
message: error.message,
|
|
265
|
+
modelId: error.modelId,
|
|
266
|
+
embeddingModelId: error.embeddingModelId,
|
|
267
|
+
webgpuAvailable: capabilities.available,
|
|
268
|
+
adapterAvailable: capabilities.adapterAvailable,
|
|
269
|
+
shaderF16Supported: capabilities.shaderF16Supported,
|
|
270
|
+
maxBufferSizeMB: capabilities.maxBufferSizeMB,
|
|
271
|
+
maxStorageBufferBindingSizeMB: capabilities.maxStorageBufferBindingSizeMB,
|
|
272
|
+
gpuVendor: capabilities.vendor,
|
|
273
|
+
gpuArchitecture: capabilities.architecture
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
const fireSuggestionInsertedAnalytics = ghostText => {
|
|
278
|
+
var _api$analytics4;
|
|
240
279
|
const typedLength = lastSuggestionTypedLength;
|
|
241
280
|
const suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
|
|
242
281
|
const kssDelta = suggestionLength - typedLength;
|
|
243
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
282
|
+
api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions.fireAnalyticsEvent({
|
|
244
283
|
action: ACTION.SUGGESTION_INSERTED,
|
|
245
284
|
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
246
285
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -253,7 +292,9 @@ export const createAutocompletePlugin = (options, api) => {
|
|
|
253
292
|
});
|
|
254
293
|
};
|
|
255
294
|
const slowLaneClient = options !== null && options !== void 0 && options.useLocalModel ? createLocalSlowLaneClient({
|
|
256
|
-
debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS
|
|
295
|
+
debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS,
|
|
296
|
+
onLoadSuccess: fireLocalModelLoadedAnalytics,
|
|
297
|
+
onLoadError: fireLocalModelLoadFailedAnalytics
|
|
257
298
|
}) : createSlowLaneClient({
|
|
258
299
|
baseUrl: '',
|
|
259
300
|
debounceMs: NETWORK_SLOW_LANE_DEBOUNCE_MS
|
|
@@ -401,9 +442,9 @@ export const createAutocompletePlugin = (options, api) => {
|
|
|
401
442
|
lastSuggestionLength = typedLength + prediction.length;
|
|
402
443
|
showGhostText(view, prediction, selection.from);
|
|
403
444
|
if (prediction !== lastShownGhostText) {
|
|
404
|
-
var _api$
|
|
445
|
+
var _api$analytics5;
|
|
405
446
|
lastShownGhostText = prediction;
|
|
406
|
-
api === null || api === void 0 ? void 0 : (_api$
|
|
447
|
+
api === null || api === void 0 ? void 0 : (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions.fireAnalyticsEvent({
|
|
407
448
|
action: ACTION.SUGGESTION_VIEWED,
|
|
408
449
|
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
409
450
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -529,13 +570,17 @@ export const createAutocompletePlugin = (options, api) => {
|
|
|
529
570
|
return false;
|
|
530
571
|
},
|
|
531
572
|
focus: () => {
|
|
532
|
-
|
|
573
|
+
var _options$useLocalMode, _options$useLocalMode2;
|
|
574
|
+
loadDefaultVocabulary({
|
|
575
|
+
isLocalLLM: (_options$useLocalMode = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode !== void 0 ? _options$useLocalMode : false
|
|
576
|
+
}).catch(error => {
|
|
533
577
|
logException(error, {
|
|
534
578
|
location: 'editor-plugin-autocomplete/loadDefaultVocabulary'
|
|
535
579
|
});
|
|
536
580
|
});
|
|
537
581
|
loadVectorsAsync({
|
|
538
|
-
getBinaryUrl: options === null || options === void 0 ? void 0 : options.getVectorsBinaryUrl
|
|
582
|
+
getBinaryUrl: options === null || options === void 0 ? void 0 : options.getVectorsBinaryUrl,
|
|
583
|
+
isLocalLLM: (_options$useLocalMode2 = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode2 !== void 0 ? _options$useLocalMode2 : false
|
|
539
584
|
}).catch(error => {
|
|
540
585
|
logException(error, {
|
|
541
586
|
location: 'editor-plugin-autocomplete/loadVectorsAsync'
|
|
@@ -43,6 +43,19 @@ import { isWordBoundary } from './slow-lane-client';
|
|
|
43
43
|
|
|
44
44
|
// Same return type as createSlowLaneClient for drop-in compatibility
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Why the local engine failed to load/start.
|
|
48
|
+
*
|
|
49
|
+
* The first three are user-machine limitations (WebGPU missing, no compatible
|
|
50
|
+
* GPU adapter, GPU lacks the `shader-f16` feature the model needs);
|
|
51
|
+
* `insufficient_memory` is hit when weights don't fit in VRAM. The rest cover
|
|
52
|
+
* delivery/runtime failures unrelated to hardware.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/** Snapshot of the machine's WebGPU support, used to explain hardware limits. */
|
|
56
|
+
|
|
57
|
+
// Minimal WebGPU shape: lib.dom types aren't guaranteed in this build target.
|
|
58
|
+
|
|
46
59
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
47
60
|
|
|
48
61
|
const DEFAULT_DEBOUNCE_MS = 300;
|
|
@@ -470,6 +483,8 @@ export const createLocalSlowLaneClient = (config = {}) => {
|
|
|
470
483
|
debounceMs = DEFAULT_DEBOUNCE_MS,
|
|
471
484
|
onUpdate,
|
|
472
485
|
onStatus,
|
|
486
|
+
onLoadError,
|
|
487
|
+
onLoadSuccess,
|
|
473
488
|
modelId = LOCAL_MLC_CAUSAL_MODEL_ID,
|
|
474
489
|
customModelConfig
|
|
475
490
|
} = config;
|
|
@@ -516,16 +531,131 @@ export const createLocalSlowLaneClient = (config = {}) => {
|
|
|
516
531
|
}
|
|
517
532
|
onStatus === null || onStatus === void 0 ? void 0 : onStatus(message);
|
|
518
533
|
};
|
|
534
|
+
const bytesToMB = bytes => typeof bytes === 'number' ? Math.round(bytes / (1024 * 1024)) : undefined;
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Inspect the machine's WebGPU support so a load failure can be attributed
|
|
538
|
+
* to a concrete hardware/browser limitation rather than a generic error.
|
|
539
|
+
*/
|
|
540
|
+
const probeWebGpuCapabilities = async () => {
|
|
541
|
+
const gpu = navigator.gpu;
|
|
542
|
+
if (!gpu) {
|
|
543
|
+
return {
|
|
544
|
+
available: false
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
var _adapter$limits, _adapter$limits2;
|
|
549
|
+
const adapter = await gpu.requestAdapter();
|
|
550
|
+
if (!adapter) {
|
|
551
|
+
return {
|
|
552
|
+
available: true,
|
|
553
|
+
adapterAvailable: false
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
let vendor;
|
|
557
|
+
let architecture;
|
|
558
|
+
try {
|
|
559
|
+
var _adapter$info, _adapter$requestAdapt;
|
|
560
|
+
const info = (_adapter$info = adapter.info) !== null && _adapter$info !== void 0 ? _adapter$info : await ((_adapter$requestAdapt = adapter.requestAdapterInfo) === null || _adapter$requestAdapt === void 0 ? void 0 : _adapter$requestAdapt.call(adapter));
|
|
561
|
+
vendor = (info === null || info === void 0 ? void 0 : info.vendor) || undefined;
|
|
562
|
+
architecture = (info === null || info === void 0 ? void 0 : info.architecture) || undefined;
|
|
563
|
+
} catch {
|
|
564
|
+
// adapter info is best-effort
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
available: true,
|
|
568
|
+
adapterAvailable: true,
|
|
569
|
+
shaderF16Supported: adapter.features.has('shader-f16'),
|
|
570
|
+
maxBufferSizeMB: bytesToMB((_adapter$limits = adapter.limits) === null || _adapter$limits === void 0 ? void 0 : _adapter$limits.maxBufferSize),
|
|
571
|
+
maxStorageBufferBindingSizeMB: bytesToMB((_adapter$limits2 = adapter.limits) === null || _adapter$limits2 === void 0 ? void 0 : _adapter$limits2.maxStorageBufferBindingSize),
|
|
572
|
+
vendor,
|
|
573
|
+
architecture
|
|
574
|
+
};
|
|
575
|
+
} catch {
|
|
576
|
+
return {
|
|
577
|
+
available: true,
|
|
578
|
+
adapterAvailable: false
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
/** Map an MLC/WebLLM engine-creation error message to a coarse reason. */
|
|
584
|
+
const classifyEngineError = message => {
|
|
585
|
+
const lower = message.toLowerCase();
|
|
586
|
+
if (lower.includes('loading chunk') || lower.includes('dynamically imported module') || lower.includes('dynamic import')) {
|
|
587
|
+
return 'module_load_failed';
|
|
588
|
+
}
|
|
589
|
+
if (lower.includes('out of memory') ||
|
|
590
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
591
|
+
/\boom\b/.test(lower) || lower.includes('allocation') || lower.includes('exceeds') || lower.includes('buffer size') || lower.includes('not enough memory')) {
|
|
592
|
+
return 'insufficient_memory';
|
|
593
|
+
}
|
|
594
|
+
// Pre-flight already returns missing_shader_f16 when the feature is absent,
|
|
595
|
+
// so only match the exact feature token here — not bare 'shader' (compile
|
|
596
|
+
// errors) or bare 'f16' (present in model ids like q0f16-MLC).
|
|
597
|
+
if (lower.includes('shader-f16') || lower.includes('shader_f16')) {
|
|
598
|
+
return 'missing_shader_f16';
|
|
599
|
+
}
|
|
600
|
+
if (lower.includes('fetch') || lower.includes('network') || lower.includes('download') || lower.includes('http') || lower.includes('cache')) {
|
|
601
|
+
return 'model_download_failed';
|
|
602
|
+
}
|
|
603
|
+
return 'init_failed';
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
// Canonical, controlled failure descriptions. We never emit the raw engine
|
|
607
|
+
// error into analytics — it can embed customer-context URLs/paths (HOT-120175)
|
|
608
|
+
// — so the analytics `message` is always one of these fixed strings.
|
|
609
|
+
const LOAD_FAILURE_MESSAGE = {
|
|
610
|
+
webgpu_unavailable: 'WebGPU is not available in this browser',
|
|
611
|
+
webgpu_no_adapter: 'No compatible WebGPU adapter found',
|
|
612
|
+
missing_shader_f16: 'GPU does not support the shader-f16 feature',
|
|
613
|
+
insufficient_memory: 'Insufficient GPU memory to load the model',
|
|
614
|
+
model_download_failed: 'Failed to download model assets',
|
|
615
|
+
module_load_failed: 'Failed to load the web-llm runtime module',
|
|
616
|
+
init_failed: 'Model engine failed to initialise'
|
|
617
|
+
};
|
|
618
|
+
const handleLoadFailure = (reason, capabilities, debugDetail) => {
|
|
619
|
+
ready = false;
|
|
620
|
+
const message = LOAD_FAILURE_MESSAGE[reason];
|
|
621
|
+
if (isAutocompleteDebugEnabled()) {
|
|
622
|
+
// eslint-disable-next-line no-console
|
|
623
|
+
console.log(`[LocalSlowLane] Engine initialisation failed (${reason}): ${debugDetail !== null && debugDetail !== void 0 ? debugDetail : message}`);
|
|
624
|
+
}
|
|
625
|
+
onStatus === null || onStatus === void 0 ? void 0 : onStatus(`Engine initialisation failed: ${message}`);
|
|
626
|
+
onLoadError === null || onLoadError === void 0 ? void 0 : onLoadError({
|
|
627
|
+
reason,
|
|
628
|
+
message,
|
|
629
|
+
modelId,
|
|
630
|
+
embeddingModelId: LOCAL_MLC_EMBEDDING_MODEL_ID,
|
|
631
|
+
capabilities
|
|
632
|
+
});
|
|
633
|
+
engineInitPromise = null;
|
|
634
|
+
initFailed = true;
|
|
635
|
+
};
|
|
519
636
|
const initEngine = async () => {
|
|
637
|
+
const capabilities = await probeWebGpuCapabilities();
|
|
638
|
+
|
|
639
|
+
// ── Pre-flight: machine limitations short-circuit before the expensive load ──
|
|
640
|
+
if (!capabilities.available) {
|
|
641
|
+
handleLoadFailure('webgpu_unavailable', capabilities);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
if (capabilities.adapterAvailable === false) {
|
|
645
|
+
handleLoadFailure('webgpu_no_adapter', capabilities);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
if (capabilities.shaderF16Supported === false) {
|
|
649
|
+
handleLoadFailure('missing_shader_f16', capabilities);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const startTime = performance.now();
|
|
520
653
|
try {
|
|
521
654
|
if (isAutocompleteDebugEnabled()) {
|
|
522
655
|
// eslint-disable-next-line no-console
|
|
523
656
|
console.log(`%c[LocalSlowLane] %c🚀 Initialising MLC engine with models: ${modelId} (LM) + ${LOCAL_MLC_EMBEDDING_MODEL_ID} (embedder)`, 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
|
|
524
657
|
}
|
|
525
658
|
onStatus === null || onStatus === void 0 ? void 0 : onStatus(`Initialising models: ${modelId} + ${LOCAL_MLC_EMBEDDING_MODEL_ID}…`);
|
|
526
|
-
if (!('gpu' in navigator)) {
|
|
527
|
-
throw new Error('WebGPU not supported');
|
|
528
|
-
}
|
|
529
659
|
|
|
530
660
|
// Fetch the web-llm runtime and the BE-parity lookup tables in parallel;
|
|
531
661
|
// both are dynamically imported so they stay out of the main editor chunk.
|
|
@@ -568,6 +698,7 @@ export const createLocalSlowLaneClient = (config = {}) => {
|
|
|
568
698
|
}
|
|
569
699
|
engine = newEngine;
|
|
570
700
|
ready = true;
|
|
701
|
+
const loadDurationMs = Math.round(performance.now() - startTime);
|
|
571
702
|
if (isAutocompleteDebugEnabled()) {
|
|
572
703
|
// eslint-disable-next-line no-console
|
|
573
704
|
console.log('%c[LocalSlowLane] %c✅ Both models loaded and ready', 'color: #9c27b0; font-weight: bold;', 'color: #4caf50;');
|
|
@@ -579,16 +710,15 @@ export const createLocalSlowLaneClient = (config = {}) => {
|
|
|
579
710
|
console.log('%c[LocalSlowLane] %c🔢 Embedder →', 'color: #9c27b0; font-weight: bold;', 'color: #009688; font-weight: bold;', LOCAL_MLC_EMBEDDING_MODEL_ID);
|
|
580
711
|
}
|
|
581
712
|
onStatus === null || onStatus === void 0 ? void 0 : onStatus('Model loaded and ready.');
|
|
713
|
+
onLoadSuccess === null || onLoadSuccess === void 0 ? void 0 : onLoadSuccess({
|
|
714
|
+
modelId,
|
|
715
|
+
embeddingModelId: LOCAL_MLC_EMBEDDING_MODEL_ID,
|
|
716
|
+
loadDurationMs,
|
|
717
|
+
capabilities
|
|
718
|
+
});
|
|
582
719
|
} catch (err) {
|
|
583
720
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
584
|
-
|
|
585
|
-
if (isAutocompleteDebugEnabled()) {
|
|
586
|
-
// eslint-disable-next-line no-console
|
|
587
|
-
console.log(`[LocalSlowLane] Engine initialisation failed: ${errorMsg}`);
|
|
588
|
-
}
|
|
589
|
-
onStatus === null || onStatus === void 0 ? void 0 : onStatus(`Engine initialisation failed: ${errorMsg}`);
|
|
590
|
-
engineInitPromise = null;
|
|
591
|
-
initFailed = true;
|
|
721
|
+
handleLoadFailure(classifyEngineError(errorMsg), capabilities, errorMsg);
|
|
592
722
|
}
|
|
593
723
|
};
|
|
594
724
|
const ensureEngineInitialized = () => {
|
|
@@ -587,6 +587,7 @@ const unwrapJsonModule = (mod, shape) => {
|
|
|
587
587
|
return null;
|
|
588
588
|
};
|
|
589
589
|
export const loadVectorsAsync = async options => {
|
|
590
|
+
var _options$isLocalLLM;
|
|
590
591
|
if (vectorStore || vectorsLoadStarted) {
|
|
591
592
|
return;
|
|
592
593
|
}
|
|
@@ -595,14 +596,18 @@ export const loadVectorsAsync = async options => {
|
|
|
595
596
|
console.warn('[text-predictor] loadVectorsAsync called without a getBinaryUrl — vectors will not load. Pass getVectorsBinaryUrl via plugin options.');
|
|
596
597
|
return;
|
|
597
598
|
}
|
|
599
|
+
const isLocalLLM = (_options$isLocalLLM = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM !== void 0 ? _options$isLocalLLM : false;
|
|
598
600
|
vectorsLoadStarted = true;
|
|
599
|
-
startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton'
|
|
601
|
+
startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
602
|
+
isLocalLLM
|
|
603
|
+
});
|
|
600
604
|
let url;
|
|
601
605
|
try {
|
|
602
606
|
url = await options.getBinaryUrl();
|
|
603
607
|
} catch (e) {
|
|
604
608
|
vectorsLoadStarted = false;
|
|
605
609
|
failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
610
|
+
isLocalLLM,
|
|
606
611
|
errorType: 'resolve_url'
|
|
607
612
|
});
|
|
608
613
|
// eslint-disable-next-line no-console
|
|
@@ -615,6 +620,7 @@ export const loadVectorsAsync = async options => {
|
|
|
615
620
|
if (!res.ok) {
|
|
616
621
|
vectorsLoadStarted = false;
|
|
617
622
|
failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
623
|
+
isLocalLLM,
|
|
618
624
|
status: res.status,
|
|
619
625
|
errorType: 'http_error'
|
|
620
626
|
});
|
|
@@ -643,6 +649,7 @@ export const loadVectorsAsync = async options => {
|
|
|
643
649
|
dim
|
|
644
650
|
};
|
|
645
651
|
succeedExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
652
|
+
isLocalLLM,
|
|
646
653
|
wordCount: nWords,
|
|
647
654
|
dim,
|
|
648
655
|
sizeBytes: float32.byteLength
|
|
@@ -658,6 +665,7 @@ export const loadVectorsAsync = async options => {
|
|
|
658
665
|
} catch (e) {
|
|
659
666
|
vectorsLoadStarted = false;
|
|
660
667
|
failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
|
|
668
|
+
isLocalLLM,
|
|
661
669
|
errorType: 'network'
|
|
662
670
|
});
|
|
663
671
|
// eslint-disable-next-line no-console
|
|
@@ -668,15 +676,19 @@ export const initVectors = store => {
|
|
|
668
676
|
vectorStore = store;
|
|
669
677
|
};
|
|
670
678
|
let vocabularyLoadPromise;
|
|
671
|
-
export const loadDefaultVocabulary =
|
|
679
|
+
export const loadDefaultVocabulary = options => {
|
|
680
|
+
var _options$isLocalLLM2;
|
|
672
681
|
if (isInitialized) {
|
|
673
682
|
return Promise.resolve();
|
|
674
683
|
}
|
|
675
684
|
if (vocabularyLoadPromise) {
|
|
676
685
|
return vocabularyLoadPromise;
|
|
677
686
|
}
|
|
687
|
+
const isLocalLLM = (_options$isLocalLLM2 = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM2 !== void 0 ? _options$isLocalLLM2 : false;
|
|
678
688
|
vocabularyLoadPromise = (async () => {
|
|
679
|
-
startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton'
|
|
689
|
+
startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
690
|
+
isLocalLLM
|
|
691
|
+
});
|
|
680
692
|
try {
|
|
681
693
|
// The L2 vocabulary and L3 word list are code-split into their own async
|
|
682
694
|
// chunks so they stay out of the editor's main bundle.
|
|
@@ -701,11 +713,13 @@ export const loadDefaultVocabulary = () => {
|
|
|
701
713
|
terms
|
|
702
714
|
});
|
|
703
715
|
succeedExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
716
|
+
isLocalLLM,
|
|
704
717
|
l2WordCount: terms.length,
|
|
705
718
|
l3WordCount: l3VocabularyData.length
|
|
706
719
|
});
|
|
707
720
|
} catch (e) {
|
|
708
721
|
failExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
|
|
722
|
+
isLocalLLM,
|
|
709
723
|
errorType: 'parse_error'
|
|
710
724
|
});
|
|
711
725
|
// Allow a later call to retry the load rather than caching the failure.
|
|
@@ -240,12 +240,49 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
|
|
|
240
240
|
}
|
|
241
241
|
});
|
|
242
242
|
};
|
|
243
|
-
var
|
|
243
|
+
var fireLocalModelLoadedAnalytics = function fireLocalModelLoadedAnalytics(info) {
|
|
244
244
|
var _api$analytics2;
|
|
245
|
+
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
|
|
246
|
+
action: ACTION.LOCAL_MODEL_LOADED,
|
|
247
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
248
|
+
eventType: EVENT_TYPE.TRACK,
|
|
249
|
+
attributes: {
|
|
250
|
+
modelId: info.modelId,
|
|
251
|
+
embeddingModelId: info.embeddingModelId,
|
|
252
|
+
loadDurationMs: info.loadDurationMs,
|
|
253
|
+
gpuVendor: info.capabilities.vendor,
|
|
254
|
+
gpuArchitecture: info.capabilities.architecture
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
var fireLocalModelLoadFailedAnalytics = function fireLocalModelLoadFailedAnalytics(error) {
|
|
259
|
+
var _api$analytics3;
|
|
260
|
+
var capabilities = error.capabilities;
|
|
261
|
+
api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.fireAnalyticsEvent({
|
|
262
|
+
action: ACTION.LOCAL_MODEL_LOAD_FAILED,
|
|
263
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
264
|
+
eventType: EVENT_TYPE.TRACK,
|
|
265
|
+
attributes: {
|
|
266
|
+
reason: error.reason,
|
|
267
|
+
message: error.message,
|
|
268
|
+
modelId: error.modelId,
|
|
269
|
+
embeddingModelId: error.embeddingModelId,
|
|
270
|
+
webgpuAvailable: capabilities.available,
|
|
271
|
+
adapterAvailable: capabilities.adapterAvailable,
|
|
272
|
+
shaderF16Supported: capabilities.shaderF16Supported,
|
|
273
|
+
maxBufferSizeMB: capabilities.maxBufferSizeMB,
|
|
274
|
+
maxStorageBufferBindingSizeMB: capabilities.maxStorageBufferBindingSizeMB,
|
|
275
|
+
gpuVendor: capabilities.vendor,
|
|
276
|
+
gpuArchitecture: capabilities.architecture
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
var fireSuggestionInsertedAnalytics = function fireSuggestionInsertedAnalytics(ghostText) {
|
|
281
|
+
var _api$analytics4;
|
|
245
282
|
var typedLength = lastSuggestionTypedLength;
|
|
246
283
|
var suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
|
|
247
284
|
var kssDelta = suggestionLength - typedLength;
|
|
248
|
-
api === null || api === void 0 || (_api$
|
|
285
|
+
api === null || api === void 0 || (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 || _api$analytics4.actions.fireAnalyticsEvent({
|
|
249
286
|
action: ACTION.SUGGESTION_INSERTED,
|
|
250
287
|
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
251
288
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -258,7 +295,9 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
|
|
|
258
295
|
});
|
|
259
296
|
};
|
|
260
297
|
var slowLaneClient = options !== null && options !== void 0 && options.useLocalModel ? createLocalSlowLaneClient({
|
|
261
|
-
debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS
|
|
298
|
+
debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS,
|
|
299
|
+
onLoadSuccess: fireLocalModelLoadedAnalytics,
|
|
300
|
+
onLoadError: fireLocalModelLoadFailedAnalytics
|
|
262
301
|
}) : createSlowLaneClient({
|
|
263
302
|
baseUrl: '',
|
|
264
303
|
debounceMs: NETWORK_SLOW_LANE_DEBOUNCE_MS
|
|
@@ -412,9 +451,9 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
|
|
|
412
451
|
lastSuggestionLength = typedLength + prediction.length;
|
|
413
452
|
showGhostText(view, prediction, selection.from);
|
|
414
453
|
if (prediction !== lastShownGhostText) {
|
|
415
|
-
var _api$
|
|
454
|
+
var _api$analytics5;
|
|
416
455
|
lastShownGhostText = prediction;
|
|
417
|
-
api === null || api === void 0 || (_api$
|
|
456
|
+
api === null || api === void 0 || (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 || _api$analytics5.actions.fireAnalyticsEvent({
|
|
418
457
|
action: ACTION.SUGGESTION_VIEWED,
|
|
419
458
|
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
420
459
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -537,13 +576,17 @@ export var createAutocompletePlugin = function createAutocompletePlugin(options,
|
|
|
537
576
|
return false;
|
|
538
577
|
},
|
|
539
578
|
focus: function focus() {
|
|
540
|
-
|
|
579
|
+
var _options$useLocalMode, _options$useLocalMode2;
|
|
580
|
+
loadDefaultVocabulary({
|
|
581
|
+
isLocalLLM: (_options$useLocalMode = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode !== void 0 ? _options$useLocalMode : false
|
|
582
|
+
}).catch(function (error) {
|
|
541
583
|
logException(error, {
|
|
542
584
|
location: 'editor-plugin-autocomplete/loadDefaultVocabulary'
|
|
543
585
|
});
|
|
544
586
|
});
|
|
545
587
|
loadVectorsAsync({
|
|
546
|
-
getBinaryUrl: options === null || options === void 0 ? void 0 : options.getVectorsBinaryUrl
|
|
588
|
+
getBinaryUrl: options === null || options === void 0 ? void 0 : options.getVectorsBinaryUrl,
|
|
589
|
+
isLocalLLM: (_options$useLocalMode2 = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode2 !== void 0 ? _options$useLocalMode2 : false
|
|
547
590
|
}).catch(function (error) {
|
|
548
591
|
logException(error, {
|
|
549
592
|
location: 'editor-plugin-autocomplete/loadVectorsAsync'
|