@atlaskit/editor-plugin-autocomplete 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @atlaskit/editor-plugin-autocomplete
2
2
 
3
+ ## 3.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`4c8cf60a51e1d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4c8cf60a51e1d) -
8
+ Fix local slow lane client declaration builds
9
+
3
10
  ## 3.2.0
4
11
 
5
12
  ### Minor Changes
@@ -129,13 +129,37 @@ var BE_PARITY = exports.BE_PARITY = {
129
129
  */
130
130
  MAX_CONTEXT_WORDS: 100
131
131
  };
132
+ var splitOnWhitespace = function splitOnWhitespace(text) {
133
+ var trimmed = text.trim();
134
+ if (trimmed === '') {
135
+ return [];
136
+ }
137
+ var words = [];
138
+ var wordStart = -1;
139
+ for (var i = 0; i < trimmed.length; i++) {
140
+ if (trimmed[i].trim() === '') {
141
+ if (wordStart !== -1) {
142
+ words.push(trimmed.slice(wordStart, i));
143
+ wordStart = -1;
144
+ }
145
+ continue;
146
+ }
147
+ if (wordStart === -1) {
148
+ wordStart = i;
149
+ }
150
+ }
151
+ if (wordStart !== -1) {
152
+ words.push(trimmed.slice(wordStart));
153
+ }
154
+ return words;
155
+ };
132
156
 
133
157
  /**
134
158
  * Return the last `n` whitespace-separated words of `text`, joined by spaces.
135
159
  * Mirrors the BE rolling-window truncation applied before both encoders.
136
160
  */
137
161
  var truncateToLastNWords = function truncateToLastNWords(text, n) {
138
- var words = text.trim().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/);
162
+ var words = splitOnWhitespace(text);
139
163
  return words.length <= n ? text : words.slice(-n).join(' ');
140
164
  };
141
165
 
@@ -749,7 +773,7 @@ var createLocalSlowLaneClient = exports.createLocalSlowLaneClient = function cre
749
773
  */
750
774
  var runInference = /*#__PURE__*/function () {
751
775
  var _ref9 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(text, requestId) {
752
- var lmText, semanticText, arcticInput, _embeddingResponse$da, tStart, tLmDone, tEmbDone, _yield$Promise$all5, _yield$Promise$all6, embeddingResponse, rawLogits, payload, embedding, sumSq, i, topTokens, errorMsg, _t2;
776
+ var lmText, semanticText, arcticInput, captureCompletionTime, _data, tStart, tLmDone, tEmbDone, _yield$Promise$all5, _yield$Promise$all6, embeddingResponse, rawLogits, payload, embedding, sumSq, i, topTokens, errorMsg, _t2;
753
777
  return _regenerator.default.wrap(function (_context3) {
754
778
  while (1) switch (_context3.prev = _context3.next) {
755
779
  case 0:
@@ -772,32 +796,36 @@ var createLocalSlowLaneClient = exports.createLocalSlowLaneClient = function cre
772
796
  lmText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_TOKENS);
773
797
  semanticText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_WORDS);
774
798
  arcticInput = wrapForArctic(semanticText);
799
+ captureCompletionTime = function captureCompletionTime(promise, onResolved) {
800
+ return promise.then(function (value) {
801
+ onResolved(performance.now());
802
+ return value;
803
+ });
804
+ };
775
805
  if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
776
806
  // eslint-disable-next-line no-console
777
- console.log("%c[LocalSlowLane] %c\uD83D\uDD22 Arctic input (".concat(arcticInput.length, " chars, ").concat(semanticText.split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/).length, " words): \"").concat(arcticInput.length > 100 ? "".concat(arcticInput.slice(0, 100), "\u2026") : arcticInput, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
807
+ console.log("%c[LocalSlowLane] %c\uD83D\uDD22 Arctic input (".concat(arcticInput.length, " chars, ").concat(splitOnWhitespace(semanticText).length, " words): \"").concat(arcticInput.length > 100 ? "".concat(arcticInput.slice(0, 100), "\u2026") : arcticInput, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
778
808
  // eslint-disable-next-line no-console
779
- console.log("%c[LocalSlowLane] %c\uD83E\uDDE0 LM input (".concat(lmText.length, " chars, ").concat(lmText.split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/).length, " words): \"").concat(lmText.length > 100 ? "".concat(lmText.slice(0, 100), "\u2026") : lmText, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
809
+ console.log("%c[LocalSlowLane] %c\uD83E\uDDE0 LM input (".concat(lmText.length, " chars, ").concat(splitOnWhitespace(lmText).length, " words): \"").concat(lmText.length > 100 ? "".concat(lmText.slice(0, 100), "\u2026") : lmText, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
780
810
  }
781
811
  _context3.prev = 2;
782
812
  tStart = performance.now();
783
813
  tLmDone = 0;
784
814
  tEmbDone = 0;
785
815
  _context3.next = 3;
786
- return Promise.all([engine.completions.create({
816
+ return Promise.all([captureCompletionTime(engine.completions.create({
787
817
  model: modelId,
788
818
  prompt: lmText,
789
819
  max_tokens: 1,
790
820
  temperature: 0,
791
821
  logprobs: false
792
- }).then(function (r) {
793
- tLmDone = performance.now();
794
- return r;
795
- }), engine.embeddings.create({
822
+ }), function (resolvedAt) {
823
+ tLmDone = resolvedAt;
824
+ }), captureCompletionTime(engine.embeddings.create({
796
825
  model: LOCAL_MLC_EMBEDDING_MODEL_ID,
797
826
  input: arcticInput
798
- }).then(function (r) {
799
- tEmbDone = performance.now();
800
- return r;
827
+ }), function (resolvedAt) {
828
+ tEmbDone = resolvedAt;
801
829
  })]);
802
830
  case 3:
803
831
  _yield$Promise$all5 = _context3.sent;
@@ -828,7 +856,7 @@ var createLocalSlowLaneClient = exports.createLocalSlowLaneClient = function cre
828
856
  // Guard against base64-encoded responses (encoding_format: 'base64' would
829
857
  // yield a string, and new Float32Array(string) silently produces an empty
830
858
  // array, corrupting downstream cosine-similarity scoring).
831
- embedding = (_embeddingResponse$da = embeddingResponse.data) === null || _embeddingResponse$da === void 0 || (_embeddingResponse$da = _embeddingResponse$da[0]) === null || _embeddingResponse$da === void 0 ? void 0 : _embeddingResponse$da.embedding;
859
+ embedding = (_data = embeddingResponse.data) === null || _data === void 0 || (_data = _data[0]) === null || _data === void 0 ? void 0 : _data.embedding;
832
860
  storedContextVector = Array.isArray(embedding) && embedding.length > 0 ? new Float32Array(embedding) : null;
833
861
  if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
834
862
  // eslint-disable-next-line no-console
@@ -109,13 +109,37 @@ export const BE_PARITY = {
109
109
  */
110
110
  MAX_CONTEXT_WORDS: 100
111
111
  };
112
+ const splitOnWhitespace = text => {
113
+ const trimmed = text.trim();
114
+ if (trimmed === '') {
115
+ return [];
116
+ }
117
+ const words = [];
118
+ let wordStart = -1;
119
+ for (let i = 0; i < trimmed.length; i++) {
120
+ if (trimmed[i].trim() === '') {
121
+ if (wordStart !== -1) {
122
+ words.push(trimmed.slice(wordStart, i));
123
+ wordStart = -1;
124
+ }
125
+ continue;
126
+ }
127
+ if (wordStart === -1) {
128
+ wordStart = i;
129
+ }
130
+ }
131
+ if (wordStart !== -1) {
132
+ words.push(trimmed.slice(wordStart));
133
+ }
134
+ return words;
135
+ };
112
136
 
113
137
  /**
114
138
  * Return the last `n` whitespace-separated words of `text`, joined by spaces.
115
139
  * Mirrors the BE rolling-window truncation applied before both encoders.
116
140
  */
117
141
  const truncateToLastNWords = (text, n) => {
118
- const words = text.trim().split(/\s+/u);
142
+ const words = splitOnWhitespace(text);
119
143
  return words.length <= n ? text : words.slice(-n).join(' ');
120
144
  };
121
145
 
@@ -600,32 +624,34 @@ export const createLocalSlowLaneClient = (config = {}) => {
600
624
  const lmText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_TOKENS);
601
625
  const semanticText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_WORDS);
602
626
  const arcticInput = wrapForArctic(semanticText);
627
+ const captureCompletionTime = (promise, onResolved) => promise.then(value => {
628
+ onResolved(performance.now());
629
+ return value;
630
+ });
603
631
  if (isAutocompleteDebugEnabled()) {
604
632
  // eslint-disable-next-line no-console
605
- console.log(`%c[LocalSlowLane] %c🔢 Arctic input (${arcticInput.length} chars, ${semanticText.split(/\s+/u).length} words): "${arcticInput.length > 100 ? `${arcticInput.slice(0, 100)}…` : arcticInput}"`, 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
633
+ console.log(`%c[LocalSlowLane] %c🔢 Arctic input (${arcticInput.length} chars, ${splitOnWhitespace(semanticText).length} words): "${arcticInput.length > 100 ? `${arcticInput.slice(0, 100)}…` : arcticInput}"`, 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
606
634
  // eslint-disable-next-line no-console
607
- console.log(`%c[LocalSlowLane] %c🧠 LM input (${lmText.length} chars, ${lmText.split(/\s+/u).length} words): "${lmText.length > 100 ? `${lmText.slice(0, 100)}…` : lmText}"`, 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
635
+ console.log(`%c[LocalSlowLane] %c🧠 LM input (${lmText.length} chars, ${splitOnWhitespace(lmText).length} words): "${lmText.length > 100 ? `${lmText.slice(0, 100)}…` : lmText}"`, 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
608
636
  }
609
637
  try {
610
- var _embeddingResponse$da, _embeddingResponse$da2;
638
+ var _data, _data$;
611
639
  const tStart = performance.now();
612
640
  let tLmDone = 0;
613
641
  let tEmbDone = 0;
614
- const [, embeddingResponse] = await Promise.all([engine.completions.create({
642
+ const [, embeddingResponse] = await Promise.all([captureCompletionTime(engine.completions.create({
615
643
  model: modelId,
616
644
  prompt: lmText,
617
645
  max_tokens: 1,
618
646
  temperature: 0,
619
647
  logprobs: false
620
- }).then(r => {
621
- tLmDone = performance.now();
622
- return r;
623
- }), engine.embeddings.create({
648
+ }), resolvedAt => {
649
+ tLmDone = resolvedAt;
650
+ }), captureCompletionTime(engine.embeddings.create({
624
651
  model: LOCAL_MLC_EMBEDDING_MODEL_ID,
625
652
  input: arcticInput
626
- }).then(r => {
627
- tEmbDone = performance.now();
628
- return r;
653
+ }), resolvedAt => {
654
+ tEmbDone = resolvedAt;
629
655
  })]);
630
656
  if (isAutocompleteDebugEnabled()) {
631
657
  // eslint-disable-next-line no-console
@@ -650,7 +676,7 @@ export const createLocalSlowLaneClient = (config = {}) => {
650
676
  // Guard against base64-encoded responses (encoding_format: 'base64' would
651
677
  // yield a string, and new Float32Array(string) silently produces an empty
652
678
  // array, corrupting downstream cosine-similarity scoring).
653
- const embedding = (_embeddingResponse$da = embeddingResponse.data) === null || _embeddingResponse$da === void 0 ? void 0 : (_embeddingResponse$da2 = _embeddingResponse$da[0]) === null || _embeddingResponse$da2 === void 0 ? void 0 : _embeddingResponse$da2.embedding;
679
+ const embedding = (_data = embeddingResponse.data) === null || _data === void 0 ? void 0 : (_data$ = _data[0]) === null || _data$ === void 0 ? void 0 : _data$.embedding;
654
680
  storedContextVector = Array.isArray(embedding) && embedding.length > 0 ? new Float32Array(embedding) : null;
655
681
  if (isAutocompleteDebugEnabled()) {
656
682
  // eslint-disable-next-line no-console
@@ -123,13 +123,37 @@ export var BE_PARITY = {
123
123
  */
124
124
  MAX_CONTEXT_WORDS: 100
125
125
  };
126
+ var splitOnWhitespace = function splitOnWhitespace(text) {
127
+ var trimmed = text.trim();
128
+ if (trimmed === '') {
129
+ return [];
130
+ }
131
+ var words = [];
132
+ var wordStart = -1;
133
+ for (var i = 0; i < trimmed.length; i++) {
134
+ if (trimmed[i].trim() === '') {
135
+ if (wordStart !== -1) {
136
+ words.push(trimmed.slice(wordStart, i));
137
+ wordStart = -1;
138
+ }
139
+ continue;
140
+ }
141
+ if (wordStart === -1) {
142
+ wordStart = i;
143
+ }
144
+ }
145
+ if (wordStart !== -1) {
146
+ words.push(trimmed.slice(wordStart));
147
+ }
148
+ return words;
149
+ };
126
150
 
127
151
  /**
128
152
  * Return the last `n` whitespace-separated words of `text`, joined by spaces.
129
153
  * Mirrors the BE rolling-window truncation applied before both encoders.
130
154
  */
131
155
  var truncateToLastNWords = function truncateToLastNWords(text, n) {
132
- var words = text.trim().split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/);
156
+ var words = splitOnWhitespace(text);
133
157
  return words.length <= n ? text : words.slice(-n).join(' ');
134
158
  };
135
159
 
@@ -737,7 +761,7 @@ export var createLocalSlowLaneClient = function createLocalSlowLaneClient() {
737
761
  */
738
762
  var runInference = /*#__PURE__*/function () {
739
763
  var _ref9 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(text, requestId) {
740
- var lmText, semanticText, arcticInput, _embeddingResponse$da, tStart, tLmDone, tEmbDone, _yield$Promise$all5, _yield$Promise$all6, embeddingResponse, rawLogits, payload, embedding, sumSq, i, topTokens, errorMsg, _t2;
764
+ var lmText, semanticText, arcticInput, captureCompletionTime, _data, tStart, tLmDone, tEmbDone, _yield$Promise$all5, _yield$Promise$all6, embeddingResponse, rawLogits, payload, embedding, sumSq, i, topTokens, errorMsg, _t2;
741
765
  return _regeneratorRuntime.wrap(function (_context3) {
742
766
  while (1) switch (_context3.prev = _context3.next) {
743
767
  case 0:
@@ -760,32 +784,36 @@ export var createLocalSlowLaneClient = function createLocalSlowLaneClient() {
760
784
  lmText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_TOKENS);
761
785
  semanticText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_WORDS);
762
786
  arcticInput = wrapForArctic(semanticText);
787
+ captureCompletionTime = function captureCompletionTime(promise, onResolved) {
788
+ return promise.then(function (value) {
789
+ onResolved(performance.now());
790
+ return value;
791
+ });
792
+ };
763
793
  if (isAutocompleteDebugEnabled()) {
764
794
  // eslint-disable-next-line no-console
765
- console.log("%c[LocalSlowLane] %c\uD83D\uDD22 Arctic input (".concat(arcticInput.length, " chars, ").concat(semanticText.split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/).length, " words): \"").concat(arcticInput.length > 100 ? "".concat(arcticInput.slice(0, 100), "\u2026") : arcticInput, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
795
+ console.log("%c[LocalSlowLane] %c\uD83D\uDD22 Arctic input (".concat(arcticInput.length, " chars, ").concat(splitOnWhitespace(semanticText).length, " words): \"").concat(arcticInput.length > 100 ? "".concat(arcticInput.slice(0, 100), "\u2026") : arcticInput, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #009688;');
766
796
  // eslint-disable-next-line no-console
767
- console.log("%c[LocalSlowLane] %c\uD83E\uDDE0 LM input (".concat(lmText.length, " chars, ").concat(lmText.split(/[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+/).length, " words): \"").concat(lmText.length > 100 ? "".concat(lmText.slice(0, 100), "\u2026") : lmText, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
797
+ console.log("%c[LocalSlowLane] %c\uD83E\uDDE0 LM input (".concat(lmText.length, " chars, ").concat(splitOnWhitespace(lmText).length, " words): \"").concat(lmText.length > 100 ? "".concat(lmText.slice(0, 100), "\u2026") : lmText, "\""), 'color: #9c27b0; font-weight: bold;', 'color: #2196f3;');
768
798
  }
769
799
  _context3.prev = 2;
770
800
  tStart = performance.now();
771
801
  tLmDone = 0;
772
802
  tEmbDone = 0;
773
803
  _context3.next = 3;
774
- return Promise.all([engine.completions.create({
804
+ return Promise.all([captureCompletionTime(engine.completions.create({
775
805
  model: modelId,
776
806
  prompt: lmText,
777
807
  max_tokens: 1,
778
808
  temperature: 0,
779
809
  logprobs: false
780
- }).then(function (r) {
781
- tLmDone = performance.now();
782
- return r;
783
- }), engine.embeddings.create({
810
+ }), function (resolvedAt) {
811
+ tLmDone = resolvedAt;
812
+ }), captureCompletionTime(engine.embeddings.create({
784
813
  model: LOCAL_MLC_EMBEDDING_MODEL_ID,
785
814
  input: arcticInput
786
- }).then(function (r) {
787
- tEmbDone = performance.now();
788
- return r;
815
+ }), function (resolvedAt) {
816
+ tEmbDone = resolvedAt;
789
817
  })]);
790
818
  case 3:
791
819
  _yield$Promise$all5 = _context3.sent;
@@ -816,7 +844,7 @@ export var createLocalSlowLaneClient = function createLocalSlowLaneClient() {
816
844
  // Guard against base64-encoded responses (encoding_format: 'base64' would
817
845
  // yield a string, and new Float32Array(string) silently produces an empty
818
846
  // array, corrupting downstream cosine-similarity scoring).
819
- embedding = (_embeddingResponse$da = embeddingResponse.data) === null || _embeddingResponse$da === void 0 || (_embeddingResponse$da = _embeddingResponse$da[0]) === null || _embeddingResponse$da === void 0 ? void 0 : _embeddingResponse$da.embedding;
847
+ embedding = (_data = embeddingResponse.data) === null || _data === void 0 || (_data = _data[0]) === null || _data === void 0 ? void 0 : _data.embedding;
820
848
  storedContextVector = Array.isArray(embedding) && embedding.length > 0 ? new Float32Array(embedding) : null;
821
849
  if (isAutocompleteDebugEnabled()) {
822
850
  // eslint-disable-next-line no-console
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Client-side text autocomplete plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -41,6 +41,7 @@ import { isAutocompleteDebugEnabled } from './debug-mode';
41
41
  import { isWordBoundary } from './slow-lane-client';
42
42
 
43
43
  type WebLlmModelRecord = NonNullable<AppConfig['model_list']>[number];
44
+ type EmbeddingApiResponse = { data?: Array<{ embedding?: unknown }> };
44
45
 
45
46
  // ─── Types ───────────────────────────────────────────────────────────────────
46
47
 
@@ -158,12 +159,42 @@ export const BE_PARITY = {
158
159
  MAX_CONTEXT_WORDS: 100,
159
160
  } as const;
160
161
 
162
+ const splitOnWhitespace = (text: string): string[] => {
163
+ const trimmed = text.trim();
164
+ if (trimmed === '') {
165
+ return [];
166
+ }
167
+
168
+ const words: string[] = [];
169
+ let wordStart = -1;
170
+
171
+ for (let i = 0; i < trimmed.length; i++) {
172
+ if (trimmed[i].trim() === '') {
173
+ if (wordStart !== -1) {
174
+ words.push(trimmed.slice(wordStart, i));
175
+ wordStart = -1;
176
+ }
177
+ continue;
178
+ }
179
+
180
+ if (wordStart === -1) {
181
+ wordStart = i;
182
+ }
183
+ }
184
+
185
+ if (wordStart !== -1) {
186
+ words.push(trimmed.slice(wordStart));
187
+ }
188
+
189
+ return words;
190
+ };
191
+
161
192
  /**
162
193
  * Return the last `n` whitespace-separated words of `text`, joined by spaces.
163
194
  * Mirrors the BE rolling-window truncation applied before both encoders.
164
195
  */
165
196
  const truncateToLastNWords = (text: string, n: number): string => {
166
- const words = text.trim().split(/\s+/u);
197
+ const words = splitOnWhitespace(text);
167
198
  return words.length <= n ? text : words.slice(-n).join(' ');
168
199
  };
169
200
 
@@ -755,17 +786,25 @@ export const createLocalSlowLaneClient = (
755
786
  const lmText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_TOKENS);
756
787
  const semanticText = truncateToLastNWords(text, BE_PARITY.MAX_CONTEXT_WORDS);
757
788
  const arcticInput = wrapForArctic(semanticText);
789
+ const captureCompletionTime = <T,>(
790
+ promise: Promise<T>,
791
+ onResolved: (resolvedAt: number) => void,
792
+ ): Promise<T> =>
793
+ promise.then((value: T) => {
794
+ onResolved(performance.now());
795
+ return value;
796
+ });
758
797
 
759
798
  if (isAutocompleteDebugEnabled()) {
760
799
  // eslint-disable-next-line no-console
761
800
  console.log(
762
- `%c[LocalSlowLane] %c🔢 Arctic input (${arcticInput.length} chars, ${semanticText.split(/\s+/u).length} words): "${arcticInput.length > 100 ? `${arcticInput.slice(0, 100)}…` : arcticInput}"`,
801
+ `%c[LocalSlowLane] %c🔢 Arctic input (${arcticInput.length} chars, ${splitOnWhitespace(semanticText).length} words): "${arcticInput.length > 100 ? `${arcticInput.slice(0, 100)}…` : arcticInput}"`,
763
802
  'color: #9c27b0; font-weight: bold;',
764
803
  'color: #009688;',
765
804
  );
766
805
  // eslint-disable-next-line no-console
767
806
  console.log(
768
- `%c[LocalSlowLane] %c🧠 LM input (${lmText.length} chars, ${lmText.split(/\s+/u).length} words): "${lmText.length > 100 ? `${lmText.slice(0, 100)}…` : lmText}"`,
807
+ `%c[LocalSlowLane] %c🧠 LM input (${lmText.length} chars, ${splitOnWhitespace(lmText).length} words): "${lmText.length > 100 ? `${lmText.slice(0, 100)}…` : lmText}"`,
769
808
  'color: #9c27b0; font-weight: bold;',
770
809
  'color: #2196f3;',
771
810
  );
@@ -777,27 +816,29 @@ export const createLocalSlowLaneClient = (
777
816
  let tEmbDone = 0;
778
817
 
779
818
  const [, embeddingResponse] = await Promise.all([
780
- engine.completions
781
- .create({
819
+ captureCompletionTime(
820
+ engine.completions.create({
782
821
  model: modelId,
783
822
  prompt: lmText,
784
823
  max_tokens: 1,
785
824
  temperature: 0,
786
825
  logprobs: false,
787
826
  })
788
- .then((r) => {
789
- tLmDone = performance.now();
790
- return r;
791
- }),
792
- engine.embeddings
793
- .create({
827
+ ,
828
+ (resolvedAt) => {
829
+ tLmDone = resolvedAt;
830
+ },
831
+ ),
832
+ captureCompletionTime(
833
+ engine.embeddings.create({
794
834
  model: LOCAL_MLC_EMBEDDING_MODEL_ID,
795
835
  input: arcticInput,
796
836
  })
797
- .then((r) => {
798
- tEmbDone = performance.now();
799
- return r;
800
- }),
837
+ ,
838
+ (resolvedAt) => {
839
+ tEmbDone = resolvedAt;
840
+ },
841
+ ),
801
842
  ]);
802
843
 
803
844
  if (isAutocompleteDebugEnabled()) {
@@ -827,7 +868,7 @@ export const createLocalSlowLaneClient = (
827
868
  // Guard against base64-encoded responses (encoding_format: 'base64' would
828
869
  // yield a string, and new Float32Array(string) silently produces an empty
829
870
  // array, corrupting downstream cosine-similarity scoring).
830
- const embedding = embeddingResponse.data?.[0]?.embedding;
871
+ const embedding = (embeddingResponse as EmbeddingApiResponse).data?.[0]?.embedding;
831
872
  storedContextVector =
832
873
  Array.isArray(embedding) && embedding.length > 0
833
874
  ? new Float32Array(embedding as number[])