@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.
@@ -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 url, _wordIndexOuter$index, res, buffer, float32, wordIndexModule, wordIndexOuter, wordIndex, nWords, dim, _t, _t2;
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 fireSuggestionInsertedAnalytics = ghostText => {
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$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent({
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$analytics3;
445
+ var _api$analytics5;
405
446
  lastShownGhostText = prediction;
406
- api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.fireAnalyticsEvent({
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
- loadDefaultVocabulary().catch(error => {
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
- ready = false;
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 fireSuggestionInsertedAnalytics = function fireSuggestionInsertedAnalytics(ghostText) {
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$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
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$analytics3;
454
+ var _api$analytics5;
416
455
  lastShownGhostText = prediction;
417
- api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.fireAnalyticsEvent({
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
- loadDefaultVocabulary().catch(function (error) {
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'