@atlaskit/editor-plugin-autocomplete 4.1.0 → 4.1.2

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.
@@ -5,6 +5,8 @@ import _createClass from "@babel/runtime/helpers/createClass";
5
5
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
6
6
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
7
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
8
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
10
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
9
11
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
12
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -732,7 +734,7 @@ function unwrapJsonModule(mod, shape) {
732
734
  export var loadVectorsAsync = /*#__PURE__*/function () {
733
735
  var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(options) {
734
736
  var _options$isLocalLLM;
735
- var isLocalLLM, url, _wordIndexOuter$index, res, buffer, float32, wordIndexModule, wordIndexOuter, wordIndex, nWords, dim, _t, _t2;
737
+ var isLocalLLM, surface, url, _wordIndexOuter$index, res, buffer, float32, wordIndexModule, wordIndexOuter, wordIndex, nWords, dim, _t, _t2;
736
738
  return _regeneratorRuntime.wrap(function (_context) {
737
739
  while (1) switch (_context.prev = _context.next) {
738
740
  case 0:
@@ -751,10 +753,13 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
751
753
  return _context.abrupt("return");
752
754
  case 2:
753
755
  isLocalLLM = (_options$isLocalLLM = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM !== void 0 ? _options$isLocalLLM : false;
756
+ surface = options === null || options === void 0 ? void 0 : options.surface;
754
757
  vectorsLoadStarted = true;
755
- startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
758
+ startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', _objectSpread({
756
759
  isLocalLLM: isLocalLLM
757
- });
760
+ }, surface ? {
761
+ surface: surface
762
+ } : {}));
758
763
  _context.prev = 3;
759
764
  _context.next = 4;
760
765
  return options.getBinaryUrl();
@@ -766,10 +771,12 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
766
771
  _context.prev = 5;
767
772
  _t = _context["catch"](3);
768
773
  vectorsLoadStarted = false;
769
- failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
774
+ failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', _objectSpread({
770
775
  isLocalLLM: isLocalLLM,
771
776
  errorType: 'resolve_url'
772
- });
777
+ }, surface ? {
778
+ surface: surface
779
+ } : {}));
773
780
  // eslint-disable-next-line no-console
774
781
  console.warn('[text-predictor] Failed to resolve vectors URL:', _t);
775
782
  return _context.abrupt("return");
@@ -784,11 +791,13 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
784
791
  break;
785
792
  }
786
793
  vectorsLoadStarted = false;
787
- failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
794
+ failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', _objectSpread({
788
795
  isLocalLLM: isLocalLLM,
789
796
  status: res.status,
790
797
  errorType: 'http_error'
791
- });
798
+ }, surface ? {
799
+ surface: surface
800
+ } : {}));
792
801
  // eslint-disable-next-line no-console
793
802
  console.warn("[text-predictor] Failed to load vectors: ".concat(res.status));
794
803
  return _context.abrupt("return");
@@ -817,12 +826,14 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
817
826
  wordIndex: wordIndex,
818
827
  dim: dim
819
828
  };
820
- succeedExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
829
+ succeedExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', _objectSpread({
821
830
  isLocalLLM: isLocalLLM,
822
831
  wordCount: nWords,
823
832
  dim: dim,
824
833
  sizeBytes: float32.byteLength
825
- });
834
+ }, surface ? {
835
+ surface: surface
836
+ } : {}));
826
837
  if (isAutocompleteDebugEnabled()) {
827
838
  // eslint-disable-next-line no-console
828
839
  console.log('[text-predictor] Vectors loaded:', {
@@ -837,10 +848,12 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
837
848
  _context.prev = 11;
838
849
  _t2 = _context["catch"](6);
839
850
  vectorsLoadStarted = false;
840
- failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
851
+ failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', _objectSpread({
841
852
  isLocalLLM: isLocalLLM,
842
853
  errorType: 'network'
843
- });
854
+ }, surface ? {
855
+ surface: surface
856
+ } : {}));
844
857
  // eslint-disable-next-line no-console
845
858
  console.warn('[text-predictor] Failed to load vectors:', _t2);
846
859
  case 12:
@@ -866,14 +879,17 @@ export var loadDefaultVocabulary = function loadDefaultVocabulary(options) {
866
879
  return vocabularyLoadPromise;
867
880
  }
868
881
  var isLocalLLM = (_options$isLocalLLM2 = options === null || options === void 0 ? void 0 : options.isLocalLLM) !== null && _options$isLocalLLM2 !== void 0 ? _options$isLocalLLM2 : false;
882
+ var surface = options === null || options === void 0 ? void 0 : options.surface;
869
883
  vocabularyLoadPromise = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
870
884
  var _yield$Promise$all, _yield$Promise$all2, vocabularyModule, l3VocabularyModule, vocabularyData, l3VocabularyData, terms, _t3;
871
885
  return _regeneratorRuntime.wrap(function (_context2) {
872
886
  while (1) switch (_context2.prev = _context2.next) {
873
887
  case 0:
874
- startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
888
+ startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', _objectSpread({
875
889
  isLocalLLM: isLocalLLM
876
- });
890
+ }, surface ? {
891
+ surface: surface
892
+ } : {}));
877
893
  _context2.prev = 1;
878
894
  _context2.next = 2;
879
895
  return Promise.all([import( /* webpackChunkName: "@atlaskit-internal_editor-plugin-autocomplete-vocabulary-10k" */'./data/vocabulary_10k.json'), import( /* webpackChunkName: "@atlaskit-internal_editor-plugin-autocomplete-l3-vocabulary" */'./data/l3_vocabulary.json')]);
@@ -907,20 +923,24 @@ export var loadDefaultVocabulary = function loadDefaultVocabulary(options) {
907
923
  initVocabulary({
908
924
  terms: terms
909
925
  });
910
- succeedExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
926
+ succeedExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', _objectSpread({
911
927
  isLocalLLM: isLocalLLM,
912
928
  l2WordCount: terms.length,
913
929
  l3WordCount: l3VocabularyData.length
914
- });
930
+ }, surface ? {
931
+ surface: surface
932
+ } : {}));
915
933
  _context2.next = 5;
916
934
  break;
917
935
  case 4:
918
936
  _context2.prev = 4;
919
937
  _t3 = _context2["catch"](1);
920
- failExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
938
+ failExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', _objectSpread({
921
939
  isLocalLLM: isLocalLLM,
922
940
  errorType: 'parse_error'
923
- });
941
+ }, surface ? {
942
+ surface: surface
943
+ } : {}));
924
944
  // Allow a later call to retry the load rather than caching the failure.
925
945
  vocabularyLoadPromise = undefined;
926
946
  throw _t3;
@@ -29,6 +29,11 @@ export interface AutocompleteContext {
29
29
  siblingCommentsContents?: string[];
30
30
  }
31
31
  export interface AutocompletePluginOptions {
32
+ /**
33
+ * Product/editor surface where autocomplete runs (e.g. "comment", "chat").
34
+ * Added to analytics and UFO metadata for cross-surface reporting.
35
+ */
36
+ surface?: string;
32
37
  /**
33
38
  * Async function called once on first editor focus to retrieve context for
34
39
  * word-frequency boosting. Called lazily so the preset can remain synchronous.
@@ -72,6 +72,8 @@ export interface LocalSlowLaneClientConfig {
72
72
  hasVector: boolean;
73
73
  textLength: number;
74
74
  }) => void;
75
+ /** Product/editor surface where autocomplete runs. */
76
+ surface?: string;
75
77
  }
76
78
  export interface LocalSlowLaneClient {
77
79
  /** Clean up resources. */
@@ -32,6 +32,7 @@ export interface SlowLaneClientConfig {
32
32
  }) => void;
33
33
  productKey?: string;
34
34
  sessionId?: string;
35
+ surface?: string;
35
36
  }
36
37
  export declare const createSlowLaneClient: (config: SlowLaneClientConfig) => {
37
38
  getContextVector: () => Float32Array | null;
@@ -83,9 +83,11 @@ export declare const predict: (textBefore: string) => string | null;
83
83
  export declare const loadVectorsAsync: (options?: {
84
84
  getBinaryUrl?: () => Promise<string>;
85
85
  isLocalLLM?: boolean;
86
+ surface?: string;
86
87
  }) => Promise<void>;
87
88
  export declare const initVectors: (store: VectorStore) => void;
88
89
  export declare const loadDefaultVocabulary: (options?: {
89
90
  isLocalLLM?: boolean;
91
+ surface?: string;
90
92
  }) => Promise<void>;
91
93
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete",
3
- "version": "4.1.0",
3
+ "version": "4.1.2",
4
4
  "description": "Client-side text autocomplete plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -8,7 +8,7 @@
8
8
  "registry": "https://registry.npmjs.org/"
9
9
  },
10
10
  "scripts": {
11
- "ak-postbuild": "ls -d dist/* | grep -v dist/types | xargs -n 1 copyfiles -u 1 -V 'src/pm-plugins/data/*.json'"
11
+ "ak-postbuild": "ls -d dist/* | xargs -n 1 copyfiles -u 1 -V src/pm-plugins/data/*.json"
12
12
  },
13
13
  "atlassian": {
14
14
  "team": "Editor: AI",
@@ -30,15 +30,21 @@
30
30
  "wink-nlp": "^2.4.0"
31
31
  },
32
32
  "peerDependencies": {
33
- "@atlaskit/editor-common": "^116.24.0",
33
+ "@atlaskit/editor-common": "^116.30.0",
34
34
  "@atlaskit/editor-plugin-analytics": "^12.0.0",
35
35
  "react": "^18.2.0"
36
36
  },
37
37
  "techstack": {
38
38
  "@atlassian/frontend": {
39
- "code-structure": ["editor-plugin"],
40
- "import-structure": ["atlassian-conventions"],
41
- "circular-dependencies": ["file-and-folder-level"]
39
+ "code-structure": [
40
+ "editor-plugin"
41
+ ],
42
+ "import-structure": [
43
+ "atlassian-conventions"
44
+ ],
45
+ "circular-dependencies": [
46
+ "file-and-folder-level"
47
+ ]
42
48
  }
43
49
  },
44
50
  "devDependencies": {
@@ -208,6 +208,11 @@ export interface AutocompleteContext {
208
208
  }
209
209
 
210
210
  export interface AutocompletePluginOptions {
211
+ /**
212
+ * Product/editor surface where autocomplete runs (e.g. "comment", "chat").
213
+ * Added to analytics and UFO metadata for cross-surface reporting.
214
+ */
215
+ surface?: string;
211
216
  /**
212
217
  * Async function called once on first editor focus to retrieve context for
213
218
  * word-frequency boosting. Called lazily so the preset can remain synchronous.
@@ -328,6 +333,7 @@ export const createAutocompletePlugin = (
328
333
  options?: AutocompletePluginOptions,
329
334
  api?: ExtractInjectionAPI<AutocompletePlugin>,
330
335
  ): SafePlugin<AutocompletePluginState> => {
336
+ const surface = options?.surface ?? 'editor';
331
337
  const locale =
332
338
  options?.locale ?? (typeof navigator !== 'undefined' ? navigator.language : undefined);
333
339
  const isAutocompleteEnabled = isEnglishLocale(locale);
@@ -375,7 +381,7 @@ export const createAutocompletePlugin = (
375
381
  action: ACTION.SUGGESTION_DISMISSED,
376
382
  actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
377
383
  eventType: EVENT_TYPE.TRACK,
378
- attributes: { completionSource: getCompletionSource(), reason },
384
+ attributes: { completionSource: getCompletionSource(), reason, surface },
379
385
  });
380
386
  };
381
387
 
@@ -390,6 +396,7 @@ export const createAutocompletePlugin = (
390
396
  loadDurationMs: info.loadDurationMs,
391
397
  gpuVendor: info.capabilities.vendor,
392
398
  gpuArchitecture: info.capabilities.architecture,
399
+ surface,
393
400
  },
394
401
  });
395
402
  };
@@ -412,6 +419,7 @@ export const createAutocompletePlugin = (
412
419
  maxStorageBufferBindingSizeMB: capabilities.maxStorageBufferBindingSizeMB,
413
420
  gpuVendor: capabilities.vendor,
414
421
  gpuArchitecture: capabilities.architecture,
422
+ surface,
415
423
  },
416
424
  });
417
425
  };
@@ -430,6 +438,7 @@ export const createAutocompletePlugin = (
430
438
  suggestionLength,
431
439
  typedLength,
432
440
  kssDelta,
441
+ surface,
433
442
  },
434
443
  });
435
444
  };
@@ -439,10 +448,12 @@ export const createAutocompletePlugin = (
439
448
  debounceMs: LOCAL_SLOW_LANE_DEBOUNCE_MS,
440
449
  onLoadSuccess: fireLocalModelLoadedAnalytics,
441
450
  onLoadError: fireLocalModelLoadFailedAnalytics,
451
+ surface,
442
452
  })
443
453
  : createSlowLaneClient({
444
454
  baseUrl: '',
445
455
  debounceMs: NETWORK_SLOW_LANE_DEBOUNCE_MS,
456
+ surface,
446
457
  });
447
458
  setDefaultSlowLaneClient(slowLaneClient);
448
459
 
@@ -632,7 +643,7 @@ export const createAutocompletePlugin = (
632
643
  action: ACTION.SUGGESTION_VIEWED,
633
644
  actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
634
645
  eventType: EVENT_TYPE.TRACK,
635
- attributes: { completionSource: getCompletionSource() },
646
+ attributes: { completionSource: getCompletionSource(), surface },
636
647
  });
637
648
  }
638
649
  }
@@ -778,7 +789,10 @@ export const createAutocompletePlugin = (
778
789
  return false;
779
790
  }
780
791
 
781
- loadDefaultVocabulary({ isLocalLLM: options?.useLocalModel ?? false }).catch((error) => {
792
+ loadDefaultVocabulary({
793
+ isLocalLLM: options?.useLocalModel ?? false,
794
+ surface,
795
+ }).catch((error) => {
782
796
  logException(error as Error, {
783
797
  location: 'editor-plugin-autocomplete/loadDefaultVocabulary',
784
798
  });
@@ -786,6 +800,7 @@ export const createAutocompletePlugin = (
786
800
  loadVectorsAsync({
787
801
  getBinaryUrl: options?.getVectorsBinaryUrl,
788
802
  isLocalLLM: options?.useLocalModel ?? false,
803
+ surface,
789
804
  }).catch((error) => {
790
805
  logException(error as Error, {
791
806
  location: 'editor-plugin-autocomplete/loadVectorsAsync',
@@ -81,6 +81,8 @@ export interface LocalSlowLaneClientConfig {
81
81
  onStatus?: (message: string) => void;
82
82
  /** Callback fired when inference returns new results. */
83
83
  onUpdate?: (opts: { hasLmLogits: boolean; hasVector: boolean; textLength: number }) => void;
84
+ /** Product/editor surface where autocomplete runs. */
85
+ surface?: string;
84
86
  }
85
87
 
86
88
  // Same return type as createSlowLaneClient for drop-in compatibility
@@ -664,6 +666,7 @@ export const createLocalSlowLaneClient = (
664
666
  onLoadSuccess,
665
667
  modelId = LOCAL_MLC_CAUSAL_MODEL_ID,
666
668
  customModelConfig,
669
+ surface,
667
670
  } = config;
668
671
 
669
672
  // ── State ──────────────────────────────────────────────────────────────
@@ -739,7 +742,9 @@ export const createLocalSlowLaneClient = (
739
742
  let vendor: string | undefined;
740
743
  let architecture: string | undefined;
741
744
  try {
742
- const info = adapter.info ?? (await adapter.requestAdapterInfo?.());
745
+ const info =
746
+ (adapter as MinimalGpuAdapter).info ??
747
+ (await (adapter as MinimalGpuAdapter).requestAdapterInfo?.());
743
748
  vendor = info?.vendor || undefined;
744
749
  architecture = info?.architecture || undefined;
745
750
  } catch {
@@ -1040,6 +1045,7 @@ export const createLocalSlowLaneClient = (
1040
1045
  startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, experienceId, {
1041
1046
  textLength: text.length,
1042
1047
  isLocalLLM: true,
1048
+ ...(surface ? { surface } : {}),
1043
1049
  });
1044
1050
 
1045
1051
  const tStart = performance.now();
@@ -1085,7 +1091,7 @@ export const createLocalSlowLaneClient = (
1085
1091
  EXPERIENCE_NAME.SLOW_LANE_FETCH,
1086
1092
  experienceId,
1087
1093
  destroyed ? 'destroyed' : 'superseded',
1088
- { isLocalLLM: true },
1094
+ { isLocalLLM: true, ...(surface ? { surface } : {}) },
1089
1095
  );
1090
1096
  return;
1091
1097
  }
@@ -1154,6 +1160,7 @@ export const createLocalSlowLaneClient = (
1154
1160
  hasVector: storedContextVector !== null,
1155
1161
  hasLmLogits: storedLmLogits !== null,
1156
1162
  isLocalLLM: true,
1163
+ ...(surface ? { surface } : {}),
1157
1164
  });
1158
1165
 
1159
1166
  onUpdate?.({
@@ -1168,7 +1175,7 @@ export const createLocalSlowLaneClient = (
1168
1175
  EXPERIENCE_NAME.SLOW_LANE_FETCH,
1169
1176
  experienceId,
1170
1177
  destroyed ? 'destroyed' : 'superseded',
1171
- { isLocalLLM: true },
1178
+ { isLocalLLM: true, ...(surface ? { surface } : {}) },
1172
1179
  );
1173
1180
  return;
1174
1181
  }
@@ -1178,6 +1185,7 @@ export const createLocalSlowLaneClient = (
1178
1185
  failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, experienceId, {
1179
1186
  errorType: 'inference',
1180
1187
  isLocalLLM: true,
1188
+ ...(surface ? { surface } : {}),
1181
1189
  });
1182
1190
  onUpdate?.({ textLength: text.length, hasVector: false, hasLmLogits: false });
1183
1191
 
@@ -54,6 +54,7 @@ export interface SlowLaneClientConfig {
54
54
  onUpdate?: (opts: { hasLmLogits: boolean; hasVector: boolean; textLength: number }) => void;
55
55
  productKey?: string;
56
56
  sessionId?: string;
57
+ surface?: string;
57
58
  }
58
59
 
59
60
  export const createSlowLaneClient = (
@@ -70,6 +71,7 @@ export const createSlowLaneClient = (
70
71
  baseUrl,
71
72
  sessionId: configSessionId,
72
73
  productKey = 'confluence',
74
+ surface,
73
75
  endpoint = '/gateway/api/v1/autocomplete/typeahead-encodings',
74
76
  debounceMs = DEFAULT_DEBOUNCE_MS,
75
77
  fetchFn = fetch,
@@ -105,6 +107,7 @@ export const createSlowLaneClient = (
105
107
  startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
106
108
  textLength: text.length,
107
109
  isLocalLLM: false,
110
+ ...(surface ? { surface } : {}),
108
111
  });
109
112
 
110
113
  if (isAutocompleteDebugEnabled()) {
@@ -136,6 +139,7 @@ export const createSlowLaneClient = (
136
139
  status: res.status,
137
140
  errorType: 'http_error',
138
141
  isLocalLLM: false,
142
+ ...(surface ? { surface } : {}),
139
143
  });
140
144
  if (isAutocompleteDebugEnabled()) {
141
145
  // eslint-disable-next-line no-console
@@ -190,6 +194,7 @@ export const createSlowLaneClient = (
190
194
  hasVector: storedContextVector !== null,
191
195
  hasLmLogits: storedLmLogits !== null,
192
196
  isLocalLLM: false,
197
+ ...(surface ? { surface } : {}),
193
198
  });
194
199
 
195
200
  onUpdate?.({
@@ -204,6 +209,7 @@ export const createSlowLaneClient = (
204
209
  failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
205
210
  errorType: 'network',
206
211
  isLocalLLM: false,
212
+ ...(surface ? { surface } : {}),
207
213
  });
208
214
  if (isAutocompleteDebugEnabled()) {
209
215
  // eslint-disable-next-line no-console
@@ -230,6 +236,7 @@ export const createSlowLaneClient = (
230
236
  if (inflightRequestId !== null) {
231
237
  abortExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, inflightRequestId, 'superseded', {
232
238
  isLocalLLM: false,
239
+ ...(surface ? { surface } : {}),
233
240
  });
234
241
  }
235
242
  const requestId = String(++requestSeq);
@@ -751,6 +751,7 @@ function unwrapJsonModule<T>(mod: unknown, shape: 'object' | 'array'): T | null
751
751
  export const loadVectorsAsync = async (options?: {
752
752
  getBinaryUrl?: () => Promise<string>;
753
753
  isLocalLLM?: boolean;
754
+ surface?: string;
754
755
  }): Promise<void> => {
755
756
  if (vectorStore || vectorsLoadStarted) {
756
757
  return;
@@ -763,15 +764,23 @@ export const loadVectorsAsync = async (options?: {
763
764
  return;
764
765
  }
765
766
  const isLocalLLM = options?.isLocalLLM ?? false;
767
+ const surface = options?.surface;
766
768
  vectorsLoadStarted = true;
767
- startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', { isLocalLLM });
769
+ startExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
770
+ isLocalLLM,
771
+ ...(surface ? { surface } : {}),
772
+ });
768
773
 
769
774
  let url: string;
770
775
  try {
771
776
  url = await options.getBinaryUrl();
772
777
  } catch (e) {
773
778
  vectorsLoadStarted = false;
774
- failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', { isLocalLLM, errorType: 'resolve_url' });
779
+ failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
780
+ isLocalLLM,
781
+ errorType: 'resolve_url',
782
+ ...(surface ? { surface } : {}),
783
+ });
775
784
  // eslint-disable-next-line no-console
776
785
  console.warn('[text-predictor] Failed to resolve vectors URL:', e);
777
786
  return;
@@ -785,6 +794,7 @@ export const loadVectorsAsync = async (options?: {
785
794
  isLocalLLM,
786
795
  status: res.status,
787
796
  errorType: 'http_error',
797
+ ...(surface ? { surface } : {}),
788
798
  });
789
799
  // eslint-disable-next-line no-console
790
800
  console.warn(`[text-predictor] Failed to load vectors: ${res.status}`);
@@ -819,6 +829,7 @@ export const loadVectorsAsync = async (options?: {
819
829
  wordCount: nWords,
820
830
  dim,
821
831
  sizeBytes: float32.byteLength,
832
+ ...(surface ? { surface } : {}),
822
833
  });
823
834
  if (isAutocompleteDebugEnabled()) {
824
835
  // eslint-disable-next-line no-console
@@ -830,7 +841,11 @@ export const loadVectorsAsync = async (options?: {
830
841
  }
831
842
  } catch (e) {
832
843
  vectorsLoadStarted = false;
833
- failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', { isLocalLLM, errorType: 'network' });
844
+ failExp(EXPERIENCE_NAME.LOAD_VECTORS, 'singleton', {
845
+ isLocalLLM,
846
+ errorType: 'network',
847
+ ...(surface ? { surface } : {}),
848
+ });
834
849
  // eslint-disable-next-line no-console
835
850
  console.warn('[text-predictor] Failed to load vectors:', e);
836
851
  }
@@ -842,7 +857,10 @@ export const initVectors = (store: VectorStore): void => {
842
857
 
843
858
  let vocabularyLoadPromise: Promise<void> | undefined;
844
859
 
845
- export const loadDefaultVocabulary = (options?: { isLocalLLM?: boolean }): Promise<void> => {
860
+ export const loadDefaultVocabulary = (options?: {
861
+ isLocalLLM?: boolean;
862
+ surface?: string;
863
+ }): Promise<void> => {
846
864
  if (isInitialized) {
847
865
  return Promise.resolve();
848
866
  }
@@ -851,8 +869,12 @@ export const loadDefaultVocabulary = (options?: { isLocalLLM?: boolean }): Promi
851
869
  }
852
870
 
853
871
  const isLocalLLM = options?.isLocalLLM ?? false;
872
+ const surface = options?.surface;
854
873
  vocabularyLoadPromise = (async () => {
855
- startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', { isLocalLLM });
874
+ startExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
875
+ isLocalLLM,
876
+ ...(surface ? { surface } : {}),
877
+ });
856
878
 
857
879
  try {
858
880
  // The L2 vocabulary and L3 word list are code-split into their own async
@@ -890,11 +912,13 @@ export const loadDefaultVocabulary = (options?: { isLocalLLM?: boolean }): Promi
890
912
  isLocalLLM,
891
913
  l2WordCount: terms.length,
892
914
  l3WordCount: l3VocabularyData.length,
915
+ ...(surface ? { surface } : {}),
893
916
  });
894
917
  } catch (e) {
895
918
  failExp(EXPERIENCE_NAME.LOAD_VOCABULARY, 'singleton', {
896
919
  isLocalLLM,
897
920
  errorType: 'parse_error',
921
+ ...(surface ? { surface } : {}),
898
922
  });
899
923
  // Allow a later call to retry the load rather than caching the failure.
900
924
  vocabularyLoadPromise = undefined;