@atlaskit/editor-plugin-autocomplete 4.0.2 → 4.0.4

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.
@@ -37,6 +37,8 @@
37
37
 
38
38
  import type { MLCEngine, InitProgressReport, AppConfig, LogitProcessor } from '@mlc-ai/web-llm';
39
39
 
40
+ import { abortExp, EXPERIENCE_NAME, failExp, startExp, succeedExp } from '../analytics/ufo';
41
+
40
42
  import { isAutocompleteDebugEnabled } from './debug-mode';
41
43
  import { isWordBoundary } from './slow-lane-client';
42
44
 
@@ -367,7 +369,7 @@ let bePayloadDataPromise: Promise<void> | undefined;
367
369
  * :param shape: `'object'` if the source JSON is `{...}`, `'array'` if `[...]`.
368
370
  * :returns: The parsed JSON value, or `null` if neither interop mode applies.
369
371
  */
370
- const unwrapJsonModule = <T>(mod: unknown, shape: 'object' | 'array'): T | null => {
372
+ function unwrapJsonModule<T>(mod: unknown, shape: 'object' | 'array'): T | null {
371
373
  if (mod == null || typeof mod !== 'object') {
372
374
  return null;
373
375
  }
@@ -409,7 +411,7 @@ const unwrapJsonModule = <T>(mod: unknown, shape: 'object' | 'array'): T | null
409
411
  }
410
412
 
411
413
  return null;
412
- };
414
+ }
413
415
 
414
416
  /**
415
417
  * Lazily load and build the BE-parity lookup tables from their JSON payloads.
@@ -987,6 +989,8 @@ export const createLocalSlowLaneClient = (
987
989
  return;
988
990
  }
989
991
 
992
+ const experienceId = String(requestId);
993
+
990
994
  // Clear the capture buffer so we read only this pass's logits. The engine
991
995
  // serialises per-model requests and updateContext is debounced, so the
992
996
  // latest request's decode step is the last to populate `captured` before
@@ -1000,14 +1004,15 @@ export const createLocalSlowLaneClient = (
1000
1004
  const lmText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_TOKENS);
1001
1005
  const semanticText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_WORDS);
1002
1006
  const arcticInput = wrapForArctic(semanticText);
1003
- const captureCompletionTime = <T>(
1007
+ function captureCompletionTime<T>(
1004
1008
  promise: Promise<T>,
1005
1009
  onResolved: (resolvedAt: number) => void,
1006
- ): Promise<T> =>
1007
- promise.then((value: T) => {
1010
+ ): Promise<T> {
1011
+ return promise.then((value: T) => {
1008
1012
  onResolved(performance.now());
1009
1013
  return value;
1010
1014
  });
1015
+ }
1011
1016
 
1012
1017
  if (isAutocompleteDebugEnabled()) {
1013
1018
  // eslint-disable-next-line no-console
@@ -1025,6 +1030,17 @@ export const createLocalSlowLaneClient = (
1025
1030
  }
1026
1031
 
1027
1032
  try {
1033
+ // Reuse the network slow-lane-fetch UFO experience (tagged isLocalLLM:true,
1034
+ // matching LOAD_VECTORS/LOAD_VOCABULARY) so on-device inference
1035
+ // latency/success-rate feeds the same FE Reliability SLO. Started inside
1036
+ // the try — post engine-init (parity with the network fetch, which
1037
+ // excludes the one-time model load) and so the catch below always
1038
+ // terminates the experience, even on a synchronous throw.
1039
+ startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, experienceId, {
1040
+ textLength: text.length,
1041
+ isLocalLLM: true,
1042
+ });
1043
+
1028
1044
  const tStart = performance.now();
1029
1045
  let tLmDone = 0;
1030
1046
  let tEmbDone = 0;
@@ -1064,6 +1080,12 @@ export const createLocalSlowLaneClient = (
1064
1080
 
1065
1081
  // Discard stale results
1066
1082
  if (requestId < latestRequestId || destroyed) {
1083
+ abortExp(
1084
+ EXPERIENCE_NAME.SLOW_LANE_FETCH,
1085
+ experienceId,
1086
+ destroyed ? 'destroyed' : 'superseded',
1087
+ { isLocalLLM: true },
1088
+ );
1067
1089
  return;
1068
1090
  }
1069
1091
 
@@ -1126,6 +1148,13 @@ export const createLocalSlowLaneClient = (
1126
1148
  console.groupEnd();
1127
1149
  }
1128
1150
 
1151
+ succeedExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, experienceId, {
1152
+ textLength: text.length,
1153
+ hasVector: storedContextVector !== null,
1154
+ hasLmLogits: storedLmLogits !== null,
1155
+ isLocalLLM: true,
1156
+ });
1157
+
1129
1158
  onUpdate?.({
1130
1159
  textLength: text.length,
1131
1160
  hasVector: storedContextVector !== null,
@@ -1134,11 +1163,21 @@ export const createLocalSlowLaneClient = (
1134
1163
  } catch (err) {
1135
1164
  // Discard errors for stale requests or after teardown
1136
1165
  if (requestId < latestRequestId || destroyed) {
1166
+ abortExp(
1167
+ EXPERIENCE_NAME.SLOW_LANE_FETCH,
1168
+ experienceId,
1169
+ destroyed ? 'destroyed' : 'superseded',
1170
+ { isLocalLLM: true },
1171
+ );
1137
1172
  return;
1138
1173
  }
1139
1174
 
1140
1175
  storedContextVector = null;
1141
1176
  storedLmLogits = null;
1177
+ failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, experienceId, {
1178
+ errorType: 'inference',
1179
+ isLocalLLM: true,
1180
+ });
1142
1181
  onUpdate?.({ textLength: text.length, hasVector: false, hasLmLogits: false });
1143
1182
 
1144
1183
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -101,7 +101,10 @@ export const createSlowLaneClient = (
101
101
  session_id: sessionId,
102
102
  };
103
103
 
104
- startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, { textLength: text.length });
104
+ startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
105
+ textLength: text.length,
106
+ isLocalLLM: false,
107
+ });
105
108
 
106
109
  if (isAutocompleteDebugEnabled()) {
107
110
  // eslint-disable-next-line no-console
@@ -131,6 +134,7 @@ export const createSlowLaneClient = (
131
134
  failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
132
135
  status: res.status,
133
136
  errorType: 'http_error',
137
+ isLocalLLM: false,
134
138
  });
135
139
  if (isAutocompleteDebugEnabled()) {
136
140
  // eslint-disable-next-line no-console
@@ -184,6 +188,7 @@ export const createSlowLaneClient = (
184
188
  textLength: text.length,
185
189
  hasVector: storedContextVector !== null,
186
190
  hasLmLogits: storedLmLogits !== null,
191
+ isLocalLLM: false,
187
192
  });
188
193
 
189
194
  onUpdate?.({
@@ -195,7 +200,10 @@ export const createSlowLaneClient = (
195
200
  } catch (e) {
196
201
  storedContextVector = null;
197
202
  storedLmLogits = null;
198
- failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, { errorType: 'network' });
203
+ failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
204
+ errorType: 'network',
205
+ isLocalLLM: false,
206
+ });
199
207
  if (isAutocompleteDebugEnabled()) {
200
208
  // eslint-disable-next-line no-console
201
209
  console.log(
@@ -219,7 +227,9 @@ export const createSlowLaneClient = (
219
227
  debounceTimer = setTimeout(() => {
220
228
  debounceTimer = null;
221
229
  if (inflightRequestId !== null) {
222
- abortExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, inflightRequestId, 'superseded');
230
+ abortExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, inflightRequestId, 'superseded', {
231
+ isLocalLLM: false,
232
+ });
223
233
  }
224
234
  const requestId = String(++requestSeq);
225
235
  inflightRequestId = requestId;
@@ -715,7 +715,7 @@ interface VocabularyJson {
715
715
  * array and a sparse numeric-keyed object are emitted identically as named
716
716
  * exports. Kept in lock-step with the matching helper in local-slow-lane-client.ts.
717
717
  */
718
- const unwrapJsonModule = <T>(mod: unknown, shape: 'object' | 'array'): T | null => {
718
+ function unwrapJsonModule<T>(mod: unknown, shape: 'object' | 'array'): T | null {
719
719
  if (mod == null || typeof mod !== 'object') {
720
720
  return null;
721
721
  }
@@ -743,7 +743,7 @@ const unwrapJsonModule = <T>(mod: unknown, shape: 'object' | 'array'): T | null
743
743
  }
744
744
 
745
745
  return null;
746
- };
746
+ }
747
747
 
748
748
  export const loadVectorsAsync = async (options?: {
749
749
  getBinaryUrl?: () => Promise<string>;