@atlaskit/editor-plugin-autocomplete 0.1.0 → 0.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/afm-cc/tsconfig.json +2 -1
  3. package/afm-jira/tsconfig.json +2 -1
  4. package/afm-products/tsconfig.json +2 -1
  5. package/build/tsconfig.json +20 -0
  6. package/build/url-module.d.ts +8 -0
  7. package/dist/cjs/autocompletePlugin.js +18 -5
  8. package/dist/cjs/autocompletePluginType.js +5 -1
  9. package/dist/cjs/pm-plugins/autocomplete-plugin.js +368 -0
  10. package/dist/cjs/pm-plugins/ghost-text-decoration.js +39 -0
  11. package/dist/cjs/pm-plugins/scoring-pipeline.js +256 -0
  12. package/dist/cjs/pm-plugins/slow-lane-client.js +199 -0
  13. package/dist/cjs/pm-plugins/text-predictor.js +796 -0
  14. package/dist/es2019/autocompletePlugin.js +20 -6
  15. package/dist/es2019/autocompletePluginType.js +1 -0
  16. package/dist/es2019/pm-plugins/autocomplete-plugin.js +368 -0
  17. package/dist/es2019/pm-plugins/ghost-text-decoration.js +33 -0
  18. package/dist/es2019/pm-plugins/scoring-pipeline.js +221 -0
  19. package/dist/es2019/pm-plugins/slow-lane-client.js +157 -0
  20. package/dist/es2019/pm-plugins/text-predictor.js +631 -0
  21. package/dist/esm/autocompletePlugin.js +18 -5
  22. package/dist/esm/autocompletePluginType.js +1 -0
  23. package/dist/esm/pm-plugins/autocomplete-plugin.js +362 -0
  24. package/dist/esm/pm-plugins/ghost-text-decoration.js +33 -0
  25. package/dist/esm/pm-plugins/scoring-pipeline.js +252 -0
  26. package/dist/esm/pm-plugins/slow-lane-client.js +192 -0
  27. package/dist/esm/pm-plugins/text-predictor.js +793 -0
  28. package/dist/types/autocompletePluginType.d.ts +6 -3
  29. package/dist/types/pm-plugins/autocomplete-plugin.d.ts +36 -0
  30. package/dist/types/pm-plugins/ghost-text-decoration.d.ts +7 -0
  31. package/dist/types/pm-plugins/scoring-pipeline.d.ts +33 -0
  32. package/dist/types/pm-plugins/slow-lane-client.d.ts +46 -0
  33. package/dist/types/pm-plugins/text-predictor.d.ts +90 -0
  34. package/dist/types-ts4.5/autocompletePluginType.d.ts +6 -3
  35. package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +36 -0
  36. package/dist/types-ts4.5/pm-plugins/ghost-text-decoration.d.ts +7 -0
  37. package/dist/types-ts4.5/pm-plugins/scoring-pipeline.d.ts +33 -0
  38. package/dist/types-ts4.5/pm-plugins/slow-lane-client.d.ts +46 -0
  39. package/dist/types-ts4.5/pm-plugins/text-predictor.d.ts +90 -0
  40. package/package.json +2 -2
  41. package/src/autocompletePlugin.tsx +25 -5
  42. package/src/autocompletePluginType.ts +14 -3
  43. package/src/pm-plugins/autocomplete-plugin/package.json +15 -0
  44. package/src/pm-plugins/autocomplete-plugin.ts +443 -0
  45. package/src/pm-plugins/data/combined_l2_l3_pos_tags.json +73571 -3
  46. package/src/pm-plugins/data/ghost_pos_tags.json +43 -3
  47. package/src/pm-plugins/data/grammar_transitions_10k.json +46 -3
  48. package/src/pm-plugins/data/l3_vocabulary.json +20002 -3
  49. package/src/pm-plugins/data/vocabulary_10k.json +38794 -3
  50. package/src/pm-plugins/data/word_index_10k.json +7760 -3
  51. package/src/pm-plugins/ghost-text-decoration.ts +44 -0
  52. package/src/pm-plugins/scoring-pipeline.ts +294 -0
  53. package/src/pm-plugins/slow-lane-client/package.json +15 -0
  54. package/src/pm-plugins/slow-lane-client.ts +222 -0
  55. package/src/pm-plugins/text-predictor/package.json +15 -0
  56. package/src/pm-plugins/text-predictor.ts +780 -0
  57. package/tsconfig.app.json +12 -3
  58. package/tsconfig.json +4 -1
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.rankCandidates = rankCandidates;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _combined_l2_l3_pos_tags = _interopRequireDefault(require("./data/combined_l2_l3_pos_tags.json"));
10
+ var _ghost_pos_tags = _interopRequireDefault(require("./data/ghost_pos_tags.json"));
11
+ var _grammar_transitions_10k = _interopRequireDefault(require("./data/grammar_transitions_10k.json"));
12
+ 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; } } }; }
13
+ 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; } }
14
+ 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; } /**
15
+ * Scoring Pipeline: Stage 1 (Semantic + Frequency), Grammar Filter, Stage 2 (LM Re-ranking).
16
+ *
17
+ * Operates synchronously on pre-loaded data. Each stage gracefully degrades
18
+ * when its required data isn't available (cold → warm → full warm).
19
+ */
20
+ // ─── Types ──────────────────────────────────────────────────
21
+
22
+ /** Metadata returned by the grammar filter for debug logging in the caller. */
23
+
24
+ // ─── Scoring Constants ──────────────────────────────────────
25
+
26
+ var ALPHA = 0.5;
27
+ var BETA = 0.5;
28
+ var NEUTRAL_SCORE = 0.5;
29
+ var STAGE1_WEIGHT = 0.6;
30
+ var STAGE2_WEIGHT = 0.4;
31
+ var MIN_STAGE1_SCORE = 0.35;
32
+ var L1_SESSION_CAP = 1.2;
33
+
34
+ // ─── Grammar Data (loaded once on import) ───────────────────
35
+
36
+ var posTags = new Map(Object.entries(_combined_l2_l3_pos_tags.default));
37
+ var grammarTransitions = _grammar_transitions_10k.default;
38
+
39
+ /**
40
+ * Precomputed map from each POS tag to the set of allowed next POS tags.
41
+ * Built once at module load from grammarTransitions so applyGrammarFilter
42
+ * never re-iterates the transition rules per call.
43
+ */
44
+ var precomputedAllowedByPos = new Map(Object.entries(grammarTransitions.transitions).map(function (_ref) {
45
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
46
+ pos = _ref2[0],
47
+ rule = _ref2[1];
48
+ return [pos, new Set(rule.allowed)];
49
+ }));
50
+
51
+ // ─── Math ───────────────────────────────────────────────────
52
+
53
+ function cosineSimilarity(a, b) {
54
+ var dot = 0;
55
+ var normA = 0;
56
+ var normB = 0;
57
+ for (var i = 0; i < a.length; i++) {
58
+ dot += a[i] * b[i];
59
+ normA += a[i] * a[i];
60
+ normB += b[i] * b[i];
61
+ }
62
+ var dNormA = Math.sqrt(normA);
63
+ var dNormB = Math.sqrt(normB);
64
+ if (dNormA === 0 || dNormB === 0) {
65
+ return NEUTRAL_SCORE;
66
+ }
67
+ return (1 + dot / (dNormA * dNormB)) / 2;
68
+ }
69
+
70
+ // ─── Stage 1: Semantic + Frequency ──────────────────────────
71
+
72
+ function scoreStage1(candidate, contextVector, getWordVector, maxTenantFreq) {
73
+ // 1. Calculate Base Global Score (Normalized Log)
74
+ var maxPossibleLog = Math.log10(maxTenantFreq + 1);
75
+
76
+ // Diversity Adjustment
77
+ var diversityRaw = (Math.log10(candidate.tenantFreq + 1) * 0.50 + Math.log10(candidate.docFreq + 1) * 0.25 + Math.log10(candidate.authorFreq + 1) * 0.25) / maxPossibleLog;
78
+ var sessionMultiplier = candidate.sessionFreq > 0 ? 1 + Math.log10(candidate.sessionFreq + 1) * 2.5 : 1;
79
+
80
+ // Apply multiplier; capped at L1_SESSION_CAP (default 1.2) to prevent excessive over-indexing
81
+ var freqScore = Math.min(diversityRaw * sessionMultiplier, L1_SESSION_CAP);
82
+
83
+ // 3. Semantic Scoring
84
+ var semanticScore = NEUTRAL_SCORE;
85
+ if (contextVector) {
86
+ var wordVec = getWordVector(candidate.word);
87
+ semanticScore = wordVec ? cosineSimilarity(contextVector, wordVec) : NEUTRAL_SCORE;
88
+ }
89
+ return {
90
+ semanticScore: semanticScore,
91
+ freqScore: freqScore,
92
+ stage1Score: ALPHA * semanticScore + BETA * freqScore
93
+ };
94
+ }
95
+
96
+ // ─── Grammar Filter ─────────────────────────────────────────
97
+
98
+ /**
99
+ * GHOST POS DICTIONARY
100
+ * A hardcoded mapping of common structural English words that were stripped
101
+ * from the main domain vocabulary. This allows the grammar filter to understand
102
+ * context without suggesting these words to the user.
103
+ */
104
+ var ghostPosTags = _ghost_pos_tags.default;
105
+ function applyGrammarFilter(candidates, previousWord) {
106
+ if (!previousWord) return {
107
+ filtered: candidates,
108
+ grammarMeta: null
109
+ };
110
+ var lowerPrev = previousWord.toLowerCase();
111
+ var prevTags = ghostPosTags[lowerPrev] || posTags.get(lowerPrev);
112
+ if (!prevTags || prevTags.length === 0) {
113
+ return {
114
+ filtered: candidates,
115
+ grammarMeta: null
116
+ };
117
+ }
118
+ var allowedNextTags;
119
+ if (prevTags.length === 1) {
120
+ var _precomputedAllowedBy;
121
+ // Common case: single POS tag — reuse the precomputed Set directly (no allocation)
122
+ allowedNextTags = (_precomputedAllowedBy = precomputedAllowedByPos.get(prevTags[0])) !== null && _precomputedAllowedBy !== void 0 ? _precomputedAllowedBy : new Set();
123
+ } else {
124
+ allowedNextTags = new Set();
125
+ var _iterator = _createForOfIteratorHelper(prevTags),
126
+ _step;
127
+ try {
128
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
129
+ var pt = _step.value;
130
+ var allowed = precomputedAllowedByPos.get(pt);
131
+ if (allowed) allowed.forEach(function (tag) {
132
+ return allowedNextTags.add(tag);
133
+ });
134
+ }
135
+ } catch (err) {
136
+ _iterator.e(err);
137
+ } finally {
138
+ _iterator.f();
139
+ }
140
+ }
141
+ var filtered = [];
142
+ var dropped = [];
143
+ var _iterator2 = _createForOfIteratorHelper(candidates),
144
+ _step2;
145
+ try {
146
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
147
+ var entry = _step2.value;
148
+ var candidateTags = posTags.get(entry.candidate.word.toLowerCase());
149
+
150
+ // If candidate has no tags (unknown word), let it pass to be safe
151
+ if (!candidateTags || candidateTags.length === 0) {
152
+ filtered.push(entry);
153
+ continue;
154
+ }
155
+ if (candidateTags.some(function (ct) {
156
+ return allowedNextTags.has(ct);
157
+ })) {
158
+ filtered.push(entry);
159
+ } else {
160
+ dropped.push(entry.candidate.word);
161
+ }
162
+ }
163
+ } catch (err) {
164
+ _iterator2.e(err);
165
+ } finally {
166
+ _iterator2.f();
167
+ }
168
+ var finalFiltered = filtered.length > 0 ? filtered : candidates;
169
+ return {
170
+ filtered: finalFiltered,
171
+ grammarMeta: {
172
+ prevWord: lowerPrev,
173
+ prevTags: prevTags,
174
+ before: candidates.length,
175
+ after: finalFiltered.length,
176
+ dropped: filtered.length > 0 ? dropped : []
177
+ }
178
+ };
179
+ }
180
+
181
+ // ─── Stage 2: LM Re-ranking ────────────────────────────────
182
+ function getLmScore(word, lmLogits) {
183
+ if (!lmLogits) return 0;
184
+
185
+ // Look up the word directly! No more tokens.
186
+ var val = lmLogits[word.toLowerCase()];
187
+ if (typeof val === 'number') {
188
+ return val;
189
+ }
190
+ return 0;
191
+ }
192
+
193
+ // ─── Public API ─────────────────────────────────────────────
194
+
195
+ function rankCandidates(candidates, contextVector, getWordVector, lmLogits, maxTenantFreq, previousWord) {
196
+ // Stage 1
197
+ var stage1Results = candidates.map(function (candidate) {
198
+ var _scoreStage = scoreStage1(candidate, contextVector, getWordVector, maxTenantFreq),
199
+ semanticScore = _scoreStage.semanticScore,
200
+ freqScore = _scoreStage.freqScore,
201
+ stage1Score = _scoreStage.stage1Score;
202
+ return {
203
+ candidate: candidate,
204
+ semanticScore: semanticScore,
205
+ freqScore: freqScore,
206
+ stage1Score: stage1Score
207
+ };
208
+ });
209
+ var stage1Survivors = stage1Results.filter(function (entry) {
210
+ return entry.stage1Score >= MIN_STAGE1_SCORE;
211
+ });
212
+
213
+ // Grammar Filter
214
+ var _applyGrammarFilter = applyGrammarFilter(stage1Survivors, previousWord),
215
+ filtered = _applyGrammarFilter.filtered,
216
+ grammarMeta = _applyGrammarFilter.grammarMeta;
217
+
218
+ // Stage 2 + final assembly
219
+ var lmMax = 0;
220
+ if (lmLogits && Object.keys(lmLogits).length > 0) {
221
+ var values = Object.values(lmLogits);
222
+ lmMax = Math.max.apply(Math, values);
223
+ }
224
+ var scored = filtered.map(function (entry) {
225
+ var lmScore = 0;
226
+ var finalScore = entry.stage1Score;
227
+ if (lmLogits && Object.keys(lmLogits).length > 0) {
228
+ var rawLm = getLmScore(entry.candidate.word, lmLogits);
229
+ if (rawLm !== 0) {
230
+ // The word was in the top_k! Score it normally.
231
+ var logitDiff = Math.log(rawLm) - Math.log(lmMax);
232
+ lmScore = Math.exp(logitDiff);
233
+ } else {
234
+ lmScore = 0.05;
235
+ }
236
+ finalScore = STAGE1_WEIGHT * entry.stage1Score + STAGE2_WEIGHT * lmScore;
237
+ }
238
+ return {
239
+ word: entry.candidate.word,
240
+ freqScore: entry.freqScore,
241
+ semanticScore: entry.semanticScore,
242
+ lmScore: lmScore,
243
+ finalScore: finalScore
244
+ };
245
+ });
246
+ scored.sort(function (a, b) {
247
+ if (b.finalScore !== a.finalScore) {
248
+ return b.finalScore - a.finalScore;
249
+ }
250
+ return a.word.length - b.word.length;
251
+ });
252
+ return {
253
+ candidates: scored,
254
+ grammarMeta: grammarMeta
255
+ };
256
+ }
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.setDefaultSlowLaneClient = exports.isWordBoundary = exports.getStoredLmLogits = exports.getStoredContextVector = exports.createSlowLaneClient = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
10
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
+ /**
12
+ * Slow Lane Client: Backend context encoding for autocomplete.
13
+ *
14
+ * Fires a BE request on word boundaries to encode document context.
15
+ * Expects the typeahead-encodings API format:
16
+ * Request: { text, session_id }
17
+ * Response: { semantic_vector: number[], lm_logits: Record<string, number> }
18
+ */
19
+
20
+ // ─── Types ───────────────────────────────────────────────────────────────────
21
+
22
+ /** Request payload for typeahead-encodings endpoint. */
23
+
24
+ /** Response from typeahead-encodings endpoint. */
25
+
26
+ // ─── Constants ───────────────────────────────────────────────────────────────
27
+
28
+ // eslint-disable-next-line require-unicode-regexp
29
+ var WORD_BOUNDARY_CHARS = /[\s.,;:!?]/;
30
+ var DEFAULT_DEBOUNCE_MS = 300;
31
+
32
+ /**
33
+ * Check if text ends with a word boundary character (space or punctuation).
34
+ */
35
+ var isWordBoundary = exports.isWordBoundary = function isWordBoundary(text) {
36
+ if (!text || text.length === 0) {
37
+ return false;
38
+ }
39
+ var lastChar = text[text.length - 1];
40
+ return WORD_BOUNDARY_CHARS.test(lastChar);
41
+ };
42
+
43
+ // ─── Slow Lane Client ────────────────────────────────────────────────────────
44
+
45
+ var createSlowLaneClient = exports.createSlowLaneClient = function createSlowLaneClient(config) {
46
+ var baseUrl = config.baseUrl,
47
+ configSessionId = config.sessionId,
48
+ _config$productKey = config.productKey,
49
+ productKey = _config$productKey === void 0 ? 'confluence' : _config$productKey,
50
+ _config$endpoint = config.endpoint,
51
+ endpoint = _config$endpoint === void 0 ? '/gateway/api/v1/autocomplete/typeahead-encodings' : _config$endpoint,
52
+ _config$debounceMs = config.debounceMs,
53
+ debounceMs = _config$debounceMs === void 0 ? DEFAULT_DEBOUNCE_MS : _config$debounceMs,
54
+ _config$fetchFn = config.fetchFn,
55
+ fetchFn = _config$fetchFn === void 0 ? fetch : _config$fetchFn,
56
+ onUpdate = config.onUpdate;
57
+ var sessionId = configSessionId !== null && configSessionId !== void 0 ? configSessionId : crypto.randomUUID();
58
+ var headers = {
59
+ 'Content-Type': 'application/json',
60
+ 'x-experience-id': 'confluence-smart-typeahead-encodings',
61
+ 'x-product': productKey
62
+ };
63
+ var debounceTimer = null;
64
+ var lastRequestedText = '';
65
+ var storedContextVector = null;
66
+ var storedLmLogits = null;
67
+ var doUpdateContext = /*#__PURE__*/function () {
68
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(text) {
69
+ var url, payload, res, data;
70
+ return _regenerator.default.wrap(function _callee$(_context) {
71
+ while (1) switch (_context.prev = _context.next) {
72
+ case 0:
73
+ if (!(!text || text.trim().length === 0)) {
74
+ _context.next = 2;
75
+ break;
76
+ }
77
+ return _context.abrupt("return");
78
+ case 2:
79
+ // eslint-disable-next-line require-unicode-regexp
80
+ url = "".concat(baseUrl.replace(/\/$/, '')).concat(endpoint);
81
+ payload = {
82
+ text: text,
83
+ session_id: sessionId
84
+ }; // Log the exact payload being sent so the comment/reply structure is visible
85
+ // eslint-disable-next-line no-console
86
+ console.groupCollapsed("%c[SlowLane] %c\uD83D\uDCE4 Sending context | ".concat(text.length, " chars"), 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
87
+ text.split('\n').forEach(function (line, i, arr) {
88
+ // eslint-disable-next-line no-console
89
+ console.log(" ".concat(i === arr.length - 1 ? '▶' : ' ', " ").concat(line));
90
+ });
91
+ // eslint-disable-next-line no-console
92
+ console.groupEnd();
93
+ _context.prev = 7;
94
+ _context.next = 10;
95
+ return fetchFn(url, {
96
+ method: 'POST',
97
+ headers: headers,
98
+ body: JSON.stringify(payload)
99
+ });
100
+ case 10:
101
+ res = _context.sent;
102
+ if (res.ok) {
103
+ _context.next = 16;
104
+ break;
105
+ }
106
+ storedContextVector = null;
107
+ storedLmLogits = null;
108
+ // eslint-disable-next-line no-console
109
+ console.log("%c[SlowLane] %c\u274C Request failed (".concat(res.status, ")"), 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
110
+ return _context.abrupt("return");
111
+ case 16:
112
+ _context.next = 18;
113
+ return res.json();
114
+ case 18:
115
+ data = _context.sent;
116
+ if (data.semantic_vector && Array.isArray(data.semantic_vector)) {
117
+ storedContextVector = new Float32Array(data.semantic_vector);
118
+ } else {
119
+ storedContextVector = null;
120
+ }
121
+ if (data.lm_logits && (0, _typeof2.default)(data.lm_logits) === 'object') {
122
+ storedLmLogits = data.lm_logits;
123
+ } else {
124
+ storedLmLogits = null;
125
+ }
126
+
127
+ // Log what came back so it can be correlated with the next prediction group
128
+ // eslint-disable-next-line no-console
129
+ console.groupCollapsed("%c[SlowLane] %c\uD83D\uDCE5 Response received", 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
130
+ // eslint-disable-next-line no-console
131
+ console.log(storedContextVector ? "\u2705 semantic_vector: ".concat(storedContextVector.length, " dims") : '❌ No semantic_vector');
132
+ // eslint-disable-next-line no-console
133
+ console.log(storedLmLogits ? "\u2705 lm_logits: ".concat(Object.keys(storedLmLogits).length, " tokens") : '❌ No lm_logits');
134
+ // eslint-disable-next-line no-console
135
+ console.groupEnd();
136
+ onUpdate === null || onUpdate === void 0 || onUpdate({
137
+ textLength: text.length,
138
+ hasVector: storedContextVector !== null,
139
+ hasLmLogits: storedLmLogits !== null
140
+ });
141
+ // eslint-disable-next-line no-unused-vars
142
+ _context.next = 33;
143
+ break;
144
+ case 28:
145
+ _context.prev = 28;
146
+ _context.t0 = _context["catch"](7);
147
+ storedContextVector = null;
148
+ storedLmLogits = null;
149
+ // eslint-disable-next-line no-console
150
+ console.log('%c[SlowLane] %c❌ Network error — context cleared', 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
151
+ case 33:
152
+ case "end":
153
+ return _context.stop();
154
+ }
155
+ }, _callee, null, [[7, 28]]);
156
+ }));
157
+ return function doUpdateContext(_x) {
158
+ return _ref.apply(this, arguments);
159
+ };
160
+ }();
161
+ var updateContextDebounced = function updateContextDebounced(text) {
162
+ if (debounceTimer) {
163
+ clearTimeout(debounceTimer);
164
+ }
165
+ lastRequestedText = text;
166
+ debounceTimer = setTimeout(function () {
167
+ debounceTimer = null;
168
+ doUpdateContext(lastRequestedText);
169
+ }, debounceMs);
170
+ };
171
+ return {
172
+ updateContext: updateContextDebounced,
173
+ getContextVector: function getContextVector() {
174
+ return storedContextVector;
175
+ },
176
+ getLmLogits: function getLmLogits() {
177
+ return storedLmLogits;
178
+ },
179
+ setContextVector: function setContextVector(vector) {
180
+ storedContextVector = vector;
181
+ },
182
+ setLmLogits: function setLmLogits(logits) {
183
+ storedLmLogits = logits;
184
+ },
185
+ isWordBoundary: isWordBoundary
186
+ };
187
+ };
188
+ var defaultSlowLaneClient = null;
189
+ var setDefaultSlowLaneClient = exports.setDefaultSlowLaneClient = function setDefaultSlowLaneClient(client) {
190
+ defaultSlowLaneClient = client;
191
+ };
192
+ var getStoredContextVector = exports.getStoredContextVector = function getStoredContextVector() {
193
+ var _defaultSlowLaneClien, _defaultSlowLaneClien2;
194
+ return (_defaultSlowLaneClien = (_defaultSlowLaneClien2 = defaultSlowLaneClient) === null || _defaultSlowLaneClien2 === void 0 ? void 0 : _defaultSlowLaneClien2.getContextVector()) !== null && _defaultSlowLaneClien !== void 0 ? _defaultSlowLaneClien : null;
195
+ };
196
+ var getStoredLmLogits = exports.getStoredLmLogits = function getStoredLmLogits() {
197
+ var _defaultSlowLaneClien3, _defaultSlowLaneClien4;
198
+ return (_defaultSlowLaneClien3 = (_defaultSlowLaneClien4 = defaultSlowLaneClient) === null || _defaultSlowLaneClien4 === void 0 ? void 0 : _defaultSlowLaneClien4.getLmLogits()) !== null && _defaultSlowLaneClien3 !== void 0 ? _defaultSlowLaneClien3 : null;
199
+ };