@atlaskit/editor-plugin-autocomplete 2.2.0 → 2.4.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/afm-cc/tsconfig.json +0 -1
  3. package/afm-products/tsconfig.json +0 -1
  4. package/autocompletePlugin/package.json +15 -0
  5. package/autocompletePluginType/package.json +15 -0
  6. package/build/tsconfig.json +0 -1
  7. package/dist/cjs/entry-points/autocompletePlugin.js +12 -0
  8. package/dist/cjs/entry-points/autocompletePluginType.js +1 -0
  9. package/dist/cjs/entry-points/src-pm-plugins-autocomplete-plugin.js +18 -0
  10. package/dist/cjs/entry-points/src-pm-plugins-slow-lane-client.js +36 -0
  11. package/dist/cjs/entry-points/src-pm-plugins-text-predictor.js +66 -0
  12. package/dist/cjs/pm-plugins/autocomplete-plugin.js +41 -14
  13. package/dist/cjs/pm-plugins/debug-mode.js +24 -0
  14. package/dist/cjs/pm-plugins/slow-lane-client.js +42 -35
  15. package/dist/cjs/pm-plugins/text-predictor.js +12 -32
  16. package/dist/es2019/entry-points/autocompletePlugin.js +2 -0
  17. package/dist/es2019/entry-points/autocompletePluginType.js +0 -0
  18. package/dist/es2019/entry-points/src-pm-plugins-autocomplete-plugin.js +2 -0
  19. package/dist/es2019/entry-points/src-pm-plugins-slow-lane-client.js +2 -0
  20. package/dist/es2019/entry-points/src-pm-plugins-text-predictor.js +2 -0
  21. package/dist/es2019/pm-plugins/autocomplete-plugin.js +41 -14
  22. package/dist/es2019/pm-plugins/debug-mode.js +18 -0
  23. package/dist/es2019/pm-plugins/slow-lane-client.js +29 -23
  24. package/dist/es2019/pm-plugins/text-predictor.js +6 -26
  25. package/dist/esm/entry-points/autocompletePlugin.js +2 -0
  26. package/dist/esm/entry-points/autocompletePluginType.js +0 -0
  27. package/dist/esm/entry-points/src-pm-plugins-autocomplete-plugin.js +2 -0
  28. package/dist/esm/entry-points/src-pm-plugins-slow-lane-client.js +2 -0
  29. package/dist/esm/entry-points/src-pm-plugins-text-predictor.js +2 -0
  30. package/dist/esm/pm-plugins/autocomplete-plugin.js +41 -14
  31. package/dist/esm/pm-plugins/debug-mode.js +18 -0
  32. package/dist/esm/pm-plugins/slow-lane-client.js +43 -35
  33. package/dist/esm/pm-plugins/text-predictor.js +11 -31
  34. package/dist/types/entry-points/autocompletePlugin.d.ts +1 -0
  35. package/dist/types/entry-points/autocompletePluginType.d.ts +1 -0
  36. package/dist/types/entry-points/src-pm-plugins-autocomplete-plugin.d.ts +2 -0
  37. package/dist/types/entry-points/src-pm-plugins-slow-lane-client.d.ts +2 -0
  38. package/dist/types/entry-points/src-pm-plugins-text-predictor.d.ts +2 -0
  39. package/dist/types/pm-plugins/autocomplete-plugin.d.ts +1 -1
  40. package/dist/types/pm-plugins/debug-mode.d.ts +12 -0
  41. package/dist/types/pm-plugins/text-predictor.d.ts +0 -2
  42. package/dist/types-ts4.5/entry-points/autocompletePlugin.d.ts +1 -0
  43. package/dist/types-ts4.5/entry-points/autocompletePluginType.d.ts +1 -0
  44. package/dist/types-ts4.5/entry-points/src-pm-plugins-autocomplete-plugin.d.ts +2 -0
  45. package/dist/types-ts4.5/entry-points/src-pm-plugins-slow-lane-client.d.ts +2 -0
  46. package/dist/types-ts4.5/entry-points/src-pm-plugins-text-predictor.d.ts +2 -0
  47. package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +1 -1
  48. package/dist/types-ts4.5/pm-plugins/debug-mode.d.ts +12 -0
  49. package/dist/types-ts4.5/pm-plugins/text-predictor.d.ts +0 -2
  50. package/package.json +3 -3
  51. package/src/entry-points/autocompletePlugin.tsx +2 -0
  52. package/src/entry-points/autocompletePluginType.ts +2 -0
  53. package/src/entry-points/src-pm-plugins-autocomplete-plugin.ts +7 -0
  54. package/src/entry-points/src-pm-plugins-slow-lane-client.ts +13 -0
  55. package/src/entry-points/src-pm-plugins-text-predictor.ts +14 -0
  56. package/src/pm-plugins/autocomplete-plugin/package.json +5 -5
  57. package/src/pm-plugins/autocomplete-plugin.ts +48 -12
  58. package/src/pm-plugins/debug-mode.ts +18 -0
  59. package/src/pm-plugins/slow-lane-client/package.json +5 -5
  60. package/src/pm-plugins/slow-lane-client.ts +53 -45
  61. package/src/pm-plugins/text-predictor/package.json +5 -5
  62. package/src/pm-plugins/text-predictor.ts +6 -30
  63. package/tsconfig.app.json +3 -1
  64. package/tsconfig.dev.json +2 -1
  65. package/afm-jira/tsconfig.json +0 -30
@@ -29,6 +29,7 @@ import l3VocabularyData from './data/l3_vocabulary.json';
29
29
  import vocabularyData from './data/vocabulary_10k.json';
30
30
  import wordIndexData from './data/word_index_10k.json';
31
31
  // import { rankCandidates, isGrammarAllowed } from './scoring-pipeline';
32
+ import { isAutocompleteDebugEnabled } from './debug-mode';
32
33
  import { rankCandidates, STAGE1_WEIGHT, STAGE2_WEIGHT, MIN_STAGE1_SCORE } from './scoring-pipeline';
33
34
  import { getStoredContextVector, getStoredLmLogits } from './slow-lane-client';
34
35
 
@@ -223,7 +224,7 @@ export var initL3Vocabulary = function initL3Vocabulary(l3Words) {
223
224
  } finally {
224
225
  _iterator5.f();
225
226
  }
226
- if (debugMode) {
227
+ if (isAutocompleteDebugEnabled()) {
227
228
  // eslint-disable-next-line no-console
228
229
  console.log("[text-predictor] L3 General English loaded: ".concat(l3Words.length, " words"));
229
230
  }
@@ -236,9 +237,7 @@ export var initL3Vocabulary = function initL3Vocabulary(l3Words) {
236
237
  var isInitialized = false;
237
238
  var vectorStore = null;
238
239
  var vectorsLoadStarted = false;
239
- var debugMode = true;
240
240
  var lastPredictionDebug = null;
241
- var hasLoggedSemanticActive = false;
242
241
 
243
242
  /** Get vector for a word from the store. */
244
243
  var getWordVector = function getWordVector(word) {
@@ -344,25 +343,12 @@ var extractPreviousWord = function extractPreviousWord(text) {
344
343
 
345
344
  // ─── Debug Helpers ───────────────────────────────────────────────────────────
346
345
 
347
- /** Enable or disable debug logging. Also checks localStorage key `autocomplete-debug`. */
348
- export var setDebugMode = function setDebugMode(enabled) {
349
- debugMode = enabled;
350
- };
351
-
352
- /** Check localStorage for autocomplete-debug on first access. */
353
- var ensureDebugModeFromStorage = function ensureDebugModeFromStorage() {
354
- if (typeof localStorage !== 'undefined' && localStorage.getItem('autocomplete-debug') === '1') {
355
- debugMode = true;
356
- }
357
- };
358
-
359
346
  /**
360
347
  * Get predictor status for debugging.
361
348
  * vectorsLoaded: true when semantic scoring is active
362
349
  * wordCount: number of words in vector store (0 if not loaded)
363
350
  */
364
351
  export var getPredictorStatus = function getPredictorStatus() {
365
- ensureDebugModeFromStorage();
366
352
  return {
367
353
  vectorsLoaded: vectorStore !== null,
368
354
  wordCount: vectorStore ? Object.keys(vectorStore.wordIndex).length : 0,
@@ -376,7 +362,6 @@ export var getPredictorStatus = function getPredictorStatus() {
376
362
  * Returns null if no prediction has run yet or debug was off.
377
363
  */
378
364
  export var getLastPredictionDebug = function getLastPredictionDebug() {
379
- ensureDebugModeFromStorage();
380
365
  return lastPredictionDebug;
381
366
  };
382
367
  export var initVocabulary = function initVocabulary(vocabulary) {
@@ -435,7 +420,7 @@ export var ingestDocumentPage = function ingestDocumentPage(pageContent) {
435
420
  } finally {
436
421
  _iterator9.f();
437
422
  }
438
- if (debugMode && validBoostedWords.size > 0) {
423
+ if (isAutocompleteDebugEnabled() && validBoostedWords.size > 0) {
439
424
  // eslint-disable-next-line no-console
440
425
  console.groupCollapsed("%c[L1 Session] %cPrimed ".concat(validBoostedWords.size, " valid dictionary words from page"), 'color: #00b8d9; font-weight: bold;', 'color: inherit; font-style: italic;');
441
426
  // eslint-disable-next-line no-console
@@ -445,7 +430,6 @@ export var ingestDocumentPage = function ingestDocumentPage(pageContent) {
445
430
  }
446
431
  };
447
432
  export var predict = function predict(textBefore) {
448
- ensureDebugModeFromStorage();
449
433
  if (!isInitialized) {
450
434
  loadDefaultVocabulary();
451
435
  }
@@ -538,7 +522,7 @@ export var predict = function predict(textBefore) {
538
522
  var lmLogits = getStoredLmLogits();
539
523
 
540
524
  // Raw LM Output Logger
541
- if (debugMode && lmLogits && Object.keys(lmLogits).length > 0) {
525
+ if (isAutocompleteDebugEnabled() && lmLogits && Object.keys(lmLogits).length > 0) {
542
526
  var rawLmTop = Object.entries(lmLogits).sort(function (a, b) {
543
527
  return b[1] - a[1];
544
528
  }).slice(0, 5).map(function (_ref) {
@@ -554,9 +538,6 @@ export var predict = function predict(textBefore) {
554
538
  console.log('%c[Raw LM Prediction]🧠', 'color: #e83e8c; font-weight: bold;', rawLmTop);
555
539
  }
556
540
  var mode = contextVector ? 'warm' : 'cold';
557
- if (debugMode && contextVector && !hasLoggedSemanticActive) {
558
- hasLoggedSemanticActive = true;
559
- }
560
541
 
561
542
  // Build ScoringCandidate array from TrieNodes
562
543
  var scoringCandidates = candidates.map(function (_ref3) {
@@ -587,7 +568,7 @@ export var predict = function predict(textBefore) {
587
568
  pipelineDebug = _rankCandidates.pipelineDebug;
588
569
  var best = ranked[0];
589
570
  var suggestion = best && best.finalScore >= MIN_SCORE_THRESHOLD ? best.word.slice(currentWord.length) : null;
590
- if (debugMode) {
571
+ if (isAutocompleteDebugEnabled()) {
591
572
  var latencyMs = performance.now() - t0;
592
573
  var tokens = tokenize(trimmed);
593
574
  var contextWords = tokens.slice(-CONTEXT_WORDS);
@@ -767,8 +748,7 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
767
748
  wordIndex: wordIndex,
768
749
  dim: dim
769
750
  };
770
- ensureDebugModeFromStorage();
771
- if (debugMode) {
751
+ if (isAutocompleteDebugEnabled()) {
772
752
  // eslint-disable-next-line no-console
773
753
  console.log('[text-predictor] Vectors loaded:', {
774
754
  wordCount: nWords,
@@ -776,19 +756,19 @@ export var loadVectorsAsync = /*#__PURE__*/function () {
776
756
  sizeBytes: float32.byteLength
777
757
  });
778
758
  }
779
- _context.next = 41;
759
+ _context.next = 40;
780
760
  break;
781
- case 37:
782
- _context.prev = 37;
761
+ case 36:
762
+ _context.prev = 36;
783
763
  _context.t1 = _context["catch"](17);
784
764
  vectorsLoadStarted = false;
785
765
  // eslint-disable-next-line no-console
786
766
  console.warn('[text-predictor] Failed to load vectors:', _context.t1);
787
- case 41:
767
+ case 40:
788
768
  case "end":
789
769
  return _context.stop();
790
770
  }
791
- }, _callee, null, [[6, 12], [17, 37]]);
771
+ }, _callee, null, [[6, 12], [17, 36]]);
792
772
  }));
793
773
  return function loadVectorsAsync(_x) {
794
774
  return _ref6.apply(this, arguments);
@@ -0,0 +1 @@
1
+ export { autocompletePlugin } from '../autocompletePlugin';
@@ -0,0 +1 @@
1
+ export type { AutocompletePlugin } from '../autocompletePluginType';
@@ -0,0 +1,2 @@
1
+ export { autocompletePluginKey, createAutocompletePlugin } from '../pm-plugins/autocomplete-plugin';
2
+ export type { AutocompleteContext, AutocompletePluginOptions, AutocompletePluginState, } from '../pm-plugins/autocomplete-plugin';
@@ -0,0 +1,2 @@
1
+ export { createSlowLaneClient, getStoredContextVector, getStoredLmLogits, isWordBoundary, setDefaultSlowLaneClient, } from '../pm-plugins/slow-lane-client';
2
+ export type { SlowLaneClientConfig, TypeaheadEncodingsRequest, TypeaheadEncodingsResponse, } from '../pm-plugins/slow-lane-client';
@@ -0,0 +1,2 @@
1
+ export { getLastPredictionDebug, getPredictorStatus, incrementSessionFreq, ingestDocumentPage, initL3Vocabulary, initVectors, initVocabulary, loadDefaultVocabulary, loadVectorsAsync, predict, } from '../pm-plugins/text-predictor';
2
+ export type { TenantVocabulary, WeightedTerm } from '../pm-plugins/text-predictor';
@@ -3,7 +3,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
4
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { AutocompletePlugin } from '../autocompletePluginType';
6
- export declare const autocompletePluginKey: PluginKey<any>;
6
+ export declare const autocompletePluginKey: PluginKey;
7
7
  export interface AutocompletePluginState {
8
8
  /** The decoration set containing the ghost text widget */
9
9
  decorationSet: DecorationSet;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Contextual Typeahead Completions (CTC) debug logging utility.
3
+ *
4
+ * Logs are silent by default. To enable in any environment (dev, staging, prod):
5
+ *
6
+ * localStorage.setItem('atl-ctc-dbg', '1')
7
+ *
8
+ * Then reload the page. To disable:
9
+ *
10
+ * localStorage.removeItem('atl-ctc-dbg')
11
+ */
12
+ export declare const isAutocompleteDebugEnabled: () => boolean;
@@ -33,8 +33,6 @@ interface VectorStore {
33
33
  * expects a simple array of strings: ["about", "above", "actually", ...]
34
34
  */
35
35
  export declare const initL3Vocabulary: (l3Words: string[]) => void;
36
- /** Enable or disable debug logging. Also checks localStorage key `autocomplete-debug`. */
37
- export declare const setDebugMode: (enabled: boolean) => void;
38
36
  /**
39
37
  * Get predictor status for debugging.
40
38
  * vectorsLoaded: true when semantic scoring is active
@@ -0,0 +1 @@
1
+ export { autocompletePlugin } from '../autocompletePlugin';
@@ -0,0 +1 @@
1
+ export type { AutocompletePlugin } from '../autocompletePluginType';
@@ -0,0 +1,2 @@
1
+ export { autocompletePluginKey, createAutocompletePlugin } from '../pm-plugins/autocomplete-plugin';
2
+ export type { AutocompleteContext, AutocompletePluginOptions, AutocompletePluginState, } from '../pm-plugins/autocomplete-plugin';
@@ -0,0 +1,2 @@
1
+ export { createSlowLaneClient, getStoredContextVector, getStoredLmLogits, isWordBoundary, setDefaultSlowLaneClient, } from '../pm-plugins/slow-lane-client';
2
+ export type { SlowLaneClientConfig, TypeaheadEncodingsRequest, TypeaheadEncodingsResponse, } from '../pm-plugins/slow-lane-client';
@@ -0,0 +1,2 @@
1
+ export { getLastPredictionDebug, getPredictorStatus, incrementSessionFreq, ingestDocumentPage, initL3Vocabulary, initVectors, initVocabulary, loadDefaultVocabulary, loadVectorsAsync, predict, } from '../pm-plugins/text-predictor';
2
+ export type { TenantVocabulary, WeightedTerm } from '../pm-plugins/text-predictor';
@@ -3,7 +3,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
3
3
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
4
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { AutocompletePlugin } from '../autocompletePluginType';
6
- export declare const autocompletePluginKey: PluginKey<any>;
6
+ export declare const autocompletePluginKey: PluginKey;
7
7
  export interface AutocompletePluginState {
8
8
  /** The decoration set containing the ghost text widget */
9
9
  decorationSet: DecorationSet;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Contextual Typeahead Completions (CTC) debug logging utility.
3
+ *
4
+ * Logs are silent by default. To enable in any environment (dev, staging, prod):
5
+ *
6
+ * localStorage.setItem('atl-ctc-dbg', '1')
7
+ *
8
+ * Then reload the page. To disable:
9
+ *
10
+ * localStorage.removeItem('atl-ctc-dbg')
11
+ */
12
+ export declare const isAutocompleteDebugEnabled: () => boolean;
@@ -33,8 +33,6 @@ interface VectorStore {
33
33
  * expects a simple array of strings: ["about", "above", "actually", ...]
34
34
  */
35
35
  export declare const initL3Vocabulary: (l3Words: string[]) => void;
36
- /** Enable or disable debug logging. Also checks localStorage key `autocomplete-debug`. */
37
- export declare const setDebugMode: (enabled: boolean) => void;
38
36
  /**
39
37
  * Get predictor status for debugging.
40
38
  * vectorsLoaded: true when semantic scoring is active
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete",
3
- "version": "2.2.0",
3
+ "version": "2.4.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",
@@ -33,8 +33,8 @@
33
33
  "wink-nlp": "^2.4.0"
34
34
  },
35
35
  "peerDependencies": {
36
- "@atlaskit/editor-common": "^114.5.0",
37
- "@atlaskit/editor-plugin-analytics": "^10.0.0",
36
+ "@atlaskit/editor-common": "^114.32.0",
37
+ "@atlaskit/editor-plugin-analytics": "^10.1.0",
38
38
  "react": "^18.2.0"
39
39
  },
40
40
  "techstack": {
@@ -0,0 +1,2 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export { autocompletePlugin } from '../autocompletePlugin';
@@ -0,0 +1,2 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export type { AutocompletePlugin } from '../autocompletePluginType';
@@ -0,0 +1,7 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export { autocompletePluginKey, createAutocompletePlugin } from '../pm-plugins/autocomplete-plugin';
3
+ export type {
4
+ AutocompleteContext,
5
+ AutocompletePluginOptions,
6
+ AutocompletePluginState,
7
+ } from '../pm-plugins/autocomplete-plugin';
@@ -0,0 +1,13 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export {
3
+ createSlowLaneClient,
4
+ getStoredContextVector,
5
+ getStoredLmLogits,
6
+ isWordBoundary,
7
+ setDefaultSlowLaneClient,
8
+ } from '../pm-plugins/slow-lane-client';
9
+ export type {
10
+ SlowLaneClientConfig,
11
+ TypeaheadEncodingsRequest,
12
+ TypeaheadEncodingsResponse,
13
+ } from '../pm-plugins/slow-lane-client';
@@ -0,0 +1,14 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export {
3
+ getLastPredictionDebug,
4
+ getPredictorStatus,
5
+ incrementSessionFreq,
6
+ ingestDocumentPage,
7
+ initL3Vocabulary,
8
+ initVectors,
9
+ initVocabulary,
10
+ loadDefaultVocabulary,
11
+ loadVectorsAsync,
12
+ predict,
13
+ } from '../pm-plugins/text-predictor';
14
+ export type { TenantVocabulary, WeightedTerm } from '../pm-plugins/text-predictor';
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete/src/pm-plugins/autocomplete-plugin",
3
- "main": "../../../dist/cjs/pm-plugins/autocomplete-plugin.js",
4
- "module": "../../../dist/esm/pm-plugins/autocomplete-plugin.js",
5
- "module:es2019": "../../../dist/es2019/pm-plugins/autocomplete-plugin.js",
3
+ "main": "../../../dist/cjs/entry-points/src-pm-plugins-autocomplete-plugin.js",
4
+ "module": "../../../dist/esm/entry-points/src-pm-plugins-autocomplete-plugin.js",
5
+ "module:es2019": "../../../dist/es2019/entry-points/src-pm-plugins-autocomplete-plugin.js",
6
6
  "sideEffects": false,
7
- "types": "../../../dist/types/pm-plugins/autocomplete-plugin.d.ts",
7
+ "types": "../../../dist/types/entry-points/src-pm-plugins-autocomplete-plugin.d.ts",
8
8
  "typesVersions": {
9
9
  ">=4.5 <5.9": {
10
10
  "*": [
11
- "../../../dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts"
11
+ "../../../dist/types-ts4.5/entry-points/src-pm-plugins-autocomplete-plugin.d.ts"
12
12
  ]
13
13
  }
14
14
  }
@@ -25,7 +25,7 @@ import {
25
25
 
26
26
  const SLOW_LANE_ENDPOINT = '/gateway/api/v1/autocomplete/typeahead-encodings';
27
27
 
28
- export const autocompletePluginKey = new PluginKey('autocomplete');
28
+ export const autocompletePluginKey: PluginKey = new PluginKey('autocomplete');
29
29
 
30
30
  const DEBOUNCE_MS = 150;
31
31
 
@@ -202,7 +202,20 @@ const buildSlowLaneText = (docText: string, context?: AutocompleteContext): stri
202
202
  return lines.join('\n');
203
203
  };
204
204
 
205
- export const createAutocompletePlugin = (options?: AutocompletePluginOptions, api?: ExtractInjectionAPI<AutocompletePlugin>) => {
205
+ const getTypedLengthForPrediction = (textBefore: string): number => {
206
+ if (isWordBoundary(textBefore)) {
207
+ return 0;
208
+ }
209
+
210
+ // eslint-disable-next-line require-unicode-regexp
211
+ const trailingToken = textBefore.match(/([^\s.,;:!?]*)$/)?.[1] ?? '';
212
+ return trailingToken.length;
213
+ };
214
+
215
+ export const createAutocompletePlugin = (
216
+ options?: AutocompletePluginOptions,
217
+ api?: ExtractInjectionAPI<AutocompletePlugin>,
218
+ ): SafePlugin<AutocompletePluginState> => {
206
219
  let debounceTimer: ReturnType<typeof setTimeout> | null = null;
207
220
  let hasIngestedPage = false;
208
221
  let resolvedContext: AutocompleteContext | undefined;
@@ -219,6 +232,25 @@ export const createAutocompletePlugin = (options?: AutocompletePluginOptions, ap
219
232
  * re-showing the same suggestion. Resets to null as soon as the text changes.
220
233
  */
221
234
  let dismissedContext: string | null = null;
235
+ let lastSuggestionTypedLength = 0;
236
+ let lastSuggestionLength = 0;
237
+
238
+ const fireSuggestionInsertedAnalytics = (ghostText: string): void => {
239
+ const typedLength = lastSuggestionTypedLength;
240
+ const suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
241
+ const kssDelta = suggestionLength - typedLength;
242
+
243
+ api?.analytics?.actions.fireAnalyticsEvent({
244
+ action: ACTION.SUGGESTION_INSERTED,
245
+ actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
246
+ eventType: EVENT_TYPE.TRACK,
247
+ attributes: {
248
+ suggestionLength,
249
+ typedLength,
250
+ kssDelta,
251
+ },
252
+ });
253
+ };
222
254
 
223
255
  const slowLaneClient = createSlowLaneClient({
224
256
  baseUrl: '',
@@ -263,6 +295,10 @@ export const createAutocompletePlugin = (options?: AutocompletePluginOptions, ap
263
295
  const prediction = predict(textBefore);
264
296
 
265
297
  if (prediction && prediction.length > 0) {
298
+ const typedLength = getTypedLengthForPrediction(textBefore);
299
+ lastSuggestionTypedLength = typedLength;
300
+ lastSuggestionLength = typedLength + prediction.length;
301
+
266
302
  showGhostText(view, prediction, selection.from);
267
303
  if (prediction !== lastShownGhostText) {
268
304
  lastShownGhostText = prediction;
@@ -359,28 +395,28 @@ export const createAutocompletePlugin = (options?: AutocompletePluginOptions, ap
359
395
 
360
396
  handleKeyDown: keydownHandler({
361
397
  Tab: (state: EditorState, dispatch?: (tr: Transaction) => void) => {
398
+ const pluginState = autocompletePluginKey.getState(state) as
399
+ | AutocompletePluginState
400
+ | undefined;
401
+ const ghostText = pluginState?.ghostText ?? '';
362
402
  const accepted = acceptGhostText(state, dispatch);
363
403
  if (accepted) {
364
404
  justAccepted = true;
365
405
  lastShownGhostText = '';
366
- api?.analytics?.actions.fireAnalyticsEvent({
367
- action: ACTION.SUGGESTION_INSERTED,
368
- actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
369
- eventType: EVENT_TYPE.TRACK,
370
- });
406
+ fireSuggestionInsertedAnalytics(ghostText);
371
407
  }
372
408
  return accepted;
373
409
  },
374
410
  ArrowRight: (state: EditorState, dispatch?: (tr: Transaction) => void) => {
411
+ const pluginState = autocompletePluginKey.getState(state) as
412
+ | AutocompletePluginState
413
+ | undefined;
414
+ const ghostText = pluginState?.ghostText ?? '';
375
415
  const accepted = acceptGhostText(state, dispatch);
376
416
  if (accepted) {
377
417
  justAccepted = true;
378
418
  lastShownGhostText = '';
379
- api?.analytics?.actions.fireAnalyticsEvent({
380
- action: ACTION.SUGGESTION_INSERTED,
381
- actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
382
- eventType: EVENT_TYPE.TRACK,
383
- });
419
+ fireSuggestionInsertedAnalytics(ghostText);
384
420
  }
385
421
  return accepted;
386
422
  },
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Contextual Typeahead Completions (CTC) debug logging utility.
3
+ *
4
+ * Logs are silent by default. To enable in any environment (dev, staging, prod):
5
+ *
6
+ * localStorage.setItem('atl-ctc-dbg', '1')
7
+ *
8
+ * Then reload the page. To disable:
9
+ *
10
+ * localStorage.removeItem('atl-ctc-dbg')
11
+ */
12
+ export const isAutocompleteDebugEnabled = (): boolean => {
13
+ try {
14
+ return typeof localStorage !== 'undefined' && localStorage.getItem('atl-ctc-dbg') === '1';
15
+ } catch {
16
+ return false;
17
+ }
18
+ };
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete/src/pm-plugins/slow-lane-client",
3
- "main": "../../../dist/cjs/pm-plugins/slow-lane-client.js",
4
- "module": "../../../dist/esm/pm-plugins/slow-lane-client.js",
5
- "module:es2019": "../../../dist/es2019/pm-plugins/slow-lane-client.js",
3
+ "main": "../../../dist/cjs/entry-points/src-pm-plugins-slow-lane-client.js",
4
+ "module": "../../../dist/esm/entry-points/src-pm-plugins-slow-lane-client.js",
5
+ "module:es2019": "../../../dist/es2019/entry-points/src-pm-plugins-slow-lane-client.js",
6
6
  "sideEffects": false,
7
- "types": "../../../dist/types/pm-plugins/slow-lane-client.d.ts",
7
+ "types": "../../../dist/types/entry-points/src-pm-plugins-slow-lane-client.d.ts",
8
8
  "typesVersions": {
9
9
  ">=4.5 <5.9": {
10
10
  "*": [
11
- "../../../dist/types-ts4.5/pm-plugins/slow-lane-client.d.ts"
11
+ "../../../dist/types-ts4.5/entry-points/src-pm-plugins-slow-lane-client.d.ts"
12
12
  ]
13
13
  }
14
14
  }
@@ -7,6 +7,8 @@
7
7
  * Response: { semantic_vector: number[], lm_logits: Record<string, number> }
8
8
  */
9
9
 
10
+ import { isAutocompleteDebugEnabled } from './debug-mode';
11
+
10
12
  // ─── Types ───────────────────────────────────────────────────────────────────
11
13
 
12
14
  /** Request payload for typeahead-encodings endpoint. */
@@ -95,19 +97,20 @@ export const createSlowLaneClient = (
95
97
  session_id: sessionId,
96
98
  };
97
99
 
98
- // Log the exact payload being sent so the comment/reply structure is visible
99
- // eslint-disable-next-line no-console
100
- console.groupCollapsed(
101
- `%c[SlowLane] %c📤 Sending context | ${text.length} chars`,
102
- 'color: #9c27b0; font-weight: bold;',
103
- 'color: inherit;',
104
- );
105
- text.split('\n').forEach((line, i, arr) => {
100
+ if (isAutocompleteDebugEnabled()) {
101
+ // eslint-disable-next-line no-console
102
+ console.groupCollapsed(
103
+ `%c[SlowLane] %c📤 Sending context | ${text.length} chars`,
104
+ 'color: #9c27b0; font-weight: bold;',
105
+ 'color: inherit;',
106
+ );
107
+ text.split('\n').forEach((line, i, arr) => {
108
+ // eslint-disable-next-line no-console
109
+ console.log(` ${i === arr.length - 1 ? '▶' : ' '} ${line}`);
110
+ });
106
111
  // eslint-disable-next-line no-console
107
- console.log(` ${i === arr.length - 1 ? '▶' : ' '} ${line}`);
108
- });
109
- // eslint-disable-next-line no-console
110
- console.groupEnd();
112
+ console.groupEnd();
113
+ }
111
114
 
112
115
  try {
113
116
  const res = await fetchFn(url, {
@@ -119,12 +122,14 @@ export const createSlowLaneClient = (
119
122
  if (!res.ok) {
120
123
  storedContextVector = null;
121
124
  storedLmLogits = null;
122
- // eslint-disable-next-line no-console
123
- console.log(
124
- `%c[SlowLane] %c❌ Request failed (${res.status})`,
125
- 'color: #9c27b0; font-weight: bold;',
126
- 'color: #f44336;',
127
- );
125
+ if (isAutocompleteDebugEnabled()) {
126
+ // eslint-disable-next-line no-console
127
+ console.log(
128
+ `%c[SlowLane] %c❌ Request failed (${res.status})`,
129
+ 'color: #9c27b0; font-weight: bold;',
130
+ 'color: #f44336;',
131
+ );
132
+ }
128
133
  return;
129
134
  }
130
135
 
@@ -142,27 +147,28 @@ export const createSlowLaneClient = (
142
147
  storedLmLogits = null;
143
148
  }
144
149
 
145
- // Log what came back so it can be correlated with the next prediction group
146
- // eslint-disable-next-line no-console
147
- console.groupCollapsed(
148
- `%c[SlowLane] %c📥 Response received`,
149
- 'color: #9c27b0; font-weight: bold;',
150
- 'color: inherit;',
151
- );
152
- // eslint-disable-next-line no-console
153
- console.log(
154
- storedContextVector
155
- ? `✅ semantic_vector: ${storedContextVector.length} dims`
156
- : '❌ No semantic_vector',
157
- );
158
- // eslint-disable-next-line no-console
159
- console.log(
160
- storedLmLogits
161
- ? `✅ lm_logits: ${Object.keys(storedLmLogits).length} tokens`
162
- : '❌ No lm_logits',
163
- );
164
- // eslint-disable-next-line no-console
165
- console.groupEnd();
150
+ if (isAutocompleteDebugEnabled()) {
151
+ // eslint-disable-next-line no-console
152
+ console.groupCollapsed(
153
+ `%c[SlowLane] %c📥 Response received`,
154
+ 'color: #9c27b0; font-weight: bold;',
155
+ 'color: inherit;',
156
+ );
157
+ // eslint-disable-next-line no-console
158
+ console.log(
159
+ storedContextVector
160
+ ? `✅ semantic_vector: ${storedContextVector.length} dims`
161
+ : '❌ No semantic_vector',
162
+ );
163
+ // eslint-disable-next-line no-console
164
+ console.log(
165
+ storedLmLogits
166
+ ? `✅ lm_logits: ${Object.keys(storedLmLogits).length} tokens`
167
+ : '❌ No lm_logits',
168
+ );
169
+ // eslint-disable-next-line no-console
170
+ console.groupEnd();
171
+ }
166
172
 
167
173
  onUpdate?.({
168
174
  textLength: text.length,
@@ -173,12 +179,14 @@ export const createSlowLaneClient = (
173
179
  } catch (e) {
174
180
  storedContextVector = null;
175
181
  storedLmLogits = null;
176
- // eslint-disable-next-line no-console
177
- console.log(
178
- '%c[SlowLane] %c❌ Network error — context cleared',
179
- 'color: #9c27b0; font-weight: bold;',
180
- 'color: #f44336;',
181
- );
182
+ if (isAutocompleteDebugEnabled()) {
183
+ // eslint-disable-next-line no-console
184
+ console.log(
185
+ '%c[SlowLane] %c❌ Network error — context cleared',
186
+ 'color: #9c27b0; font-weight: bold;',
187
+ 'color: #f44336;',
188
+ );
189
+ }
182
190
  }
183
191
  };
184
192
 
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-autocomplete/src/pm-plugins/text-predictor",
3
- "main": "../../../dist/cjs/pm-plugins/text-predictor.js",
4
- "module": "../../../dist/esm/pm-plugins/text-predictor.js",
5
- "module:es2019": "../../../dist/es2019/pm-plugins/text-predictor.js",
3
+ "main": "../../../dist/cjs/entry-points/src-pm-plugins-text-predictor.js",
4
+ "module": "../../../dist/esm/entry-points/src-pm-plugins-text-predictor.js",
5
+ "module:es2019": "../../../dist/es2019/entry-points/src-pm-plugins-text-predictor.js",
6
6
  "sideEffects": false,
7
- "types": "../../../dist/types/pm-plugins/text-predictor.d.ts",
7
+ "types": "../../../dist/types/entry-points/src-pm-plugins-text-predictor.d.ts",
8
8
  "typesVersions": {
9
9
  ">=4.5 <5.9": {
10
10
  "*": [
11
- "../../../dist/types-ts4.5/pm-plugins/text-predictor.d.ts"
11
+ "../../../dist/types-ts4.5/entry-points/src-pm-plugins-text-predictor.d.ts"
12
12
  ]
13
13
  }
14
14
  }