@atlaskit/editor-plugin-autocomplete 2.1.0 → 2.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 +22 -0
- package/afm-cc/tsconfig.json +3 -1
- package/afm-products/tsconfig.json +3 -1
- package/build/tsconfig.json +0 -1
- package/dist/cjs/autocompletePlugin.js +3 -2
- package/dist/cjs/pm-plugins/autocomplete-plugin.js +59 -3
- package/dist/cjs/pm-plugins/debug-mode.js +24 -0
- package/dist/cjs/pm-plugins/slow-lane-client.js +42 -35
- package/dist/cjs/pm-plugins/text-predictor.js +12 -32
- package/dist/es2019/autocompletePlugin.js +3 -2
- package/dist/es2019/pm-plugins/autocomplete-plugin.js +59 -3
- package/dist/es2019/pm-plugins/debug-mode.js +18 -0
- package/dist/es2019/pm-plugins/slow-lane-client.js +29 -23
- package/dist/es2019/pm-plugins/text-predictor.js +6 -26
- package/dist/esm/autocompletePlugin.js +3 -2
- package/dist/esm/pm-plugins/autocomplete-plugin.js +59 -3
- package/dist/esm/pm-plugins/debug-mode.js +18 -0
- package/dist/esm/pm-plugins/slow-lane-client.js +43 -35
- package/dist/esm/pm-plugins/text-predictor.js +11 -31
- package/dist/types/autocompletePluginType.d.ts +3 -1
- package/dist/types/pm-plugins/autocomplete-plugin.d.ts +4 -2
- package/dist/types/pm-plugins/debug-mode.d.ts +12 -0
- package/dist/types/pm-plugins/text-predictor.d.ts +0 -2
- package/dist/types-ts4.5/autocompletePluginType.d.ts +5 -1
- package/dist/types-ts4.5/pm-plugins/autocomplete-plugin.d.ts +4 -2
- package/dist/types-ts4.5/pm-plugins/debug-mode.d.ts +12 -0
- package/dist/types-ts4.5/pm-plugins/text-predictor.d.ts +0 -2
- package/package.json +3 -2
- package/src/autocompletePlugin.tsx +2 -2
- package/src/autocompletePluginType.ts +3 -1
- package/src/pm-plugins/autocomplete-plugin.ts +70 -4
- package/src/pm-plugins/debug-mode.ts +18 -0
- package/src/pm-plugins/slow-lane-client.ts +53 -45
- package/src/pm-plugins/text-predictor.ts +12 -34
- package/tsconfig.app.json +6 -1
- package/tsconfig.dev.json +2 -1
- package/afm-jira/tsconfig.json +0 -30
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-autocomplete
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`975a31aae73f4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/975a31aae73f4) -
|
|
8
|
+
Add KSS attributes to contextual typeahead acceptance analytics
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
14
|
+
## 2.2.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- [`6eb5747f5ba37`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6eb5747f5ba37) -
|
|
19
|
+
Add SAR analytics for autocomplete plugin
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
|
|
3
25
|
## 2.1.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/afm-cc/tsconfig.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../../../tsconfig.local-consumption.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"target": "es5",
|
|
5
4
|
"outDir": "../../../../../confluence/tsDist/@atlaskit__editor-plugin-autocomplete",
|
|
6
5
|
"rootDir": "../",
|
|
7
6
|
"composite": true,
|
|
@@ -25,6 +24,9 @@
|
|
|
25
24
|
},
|
|
26
25
|
{
|
|
27
26
|
"path": "../../editor-common/afm-cc/tsconfig.json"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "../../editor-plugin-analytics/afm-cc/tsconfig.json"
|
|
28
30
|
}
|
|
29
31
|
]
|
|
30
32
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../../../tsconfig.local-consumption.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"target": "es5",
|
|
5
4
|
"outDir": "../../../../../tsDist/@atlaskit__editor-plugin-autocomplete/app",
|
|
6
5
|
"rootDir": "../",
|
|
7
6
|
"composite": true,
|
|
@@ -25,6 +24,9 @@
|
|
|
25
24
|
},
|
|
26
25
|
{
|
|
27
26
|
"path": "../../editor-common/afm-products/tsconfig.json"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "../../editor-plugin-analytics/afm-products/tsconfig.json"
|
|
28
30
|
}
|
|
29
31
|
]
|
|
30
32
|
}
|
package/build/tsconfig.json
CHANGED
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.autocompletePlugin = void 0;
|
|
7
7
|
var _autocompletePlugin = require("./pm-plugins/autocomplete-plugin");
|
|
8
8
|
var autocompletePlugin = exports.autocompletePlugin = function autocompletePlugin(_ref) {
|
|
9
|
-
var options = _ref.config
|
|
9
|
+
var options = _ref.config,
|
|
10
|
+
api = _ref.api;
|
|
10
11
|
return {
|
|
11
12
|
name: 'autocomplete',
|
|
12
13
|
getSharedState: function getSharedState(editorState) {
|
|
@@ -19,7 +20,7 @@ var autocompletePlugin = exports.autocompletePlugin = function autocompletePlugi
|
|
|
19
20
|
return [{
|
|
20
21
|
name: 'autocomplete',
|
|
21
22
|
plugin: function plugin() {
|
|
22
|
-
return (0, _autocompletePlugin.createAutocompletePlugin)(options);
|
|
23
|
+
return (0, _autocompletePlugin.createAutocompletePlugin)(options, api);
|
|
23
24
|
}
|
|
24
25
|
}];
|
|
25
26
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createAutocompletePlugin = exports.autocompletePluginKey = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
9
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
10
11
|
var _keymap = require("@atlaskit/editor-prosemirror/keymap");
|
|
11
12
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
@@ -68,6 +69,7 @@ var setAutocompleteMeta = function setAutocompleteMeta(tr, meta) {
|
|
|
68
69
|
/**
|
|
69
70
|
* Apply a ghost text suggestion to the editor state.
|
|
70
71
|
*/
|
|
72
|
+
var lastShownGhostText = '';
|
|
71
73
|
var showGhostText = function showGhostText(view, text, position) {
|
|
72
74
|
var state = view.state,
|
|
73
75
|
dispatch = view.dispatch;
|
|
@@ -146,7 +148,17 @@ var buildSlowLaneText = function buildSlowLaneText(docText, context) {
|
|
|
146
148
|
lines.push("reply ".concat(nextReplyNumber, ": ").concat(docText));
|
|
147
149
|
return lines.join('\n');
|
|
148
150
|
};
|
|
149
|
-
var
|
|
151
|
+
var getTypedLengthForPrediction = function getTypedLengthForPrediction(textBefore) {
|
|
152
|
+
var _textBefore$match$, _textBefore$match;
|
|
153
|
+
if ((0, _slowLaneClient.isWordBoundary)(textBefore)) {
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
158
|
+
var trailingToken = (_textBefore$match$ = (_textBefore$match = textBefore.match(/([^\s.,;:!?]*)$/)) === null || _textBefore$match === void 0 ? void 0 : _textBefore$match[1]) !== null && _textBefore$match$ !== void 0 ? _textBefore$match$ : '';
|
|
159
|
+
return trailingToken.length;
|
|
160
|
+
};
|
|
161
|
+
var createAutocompletePlugin = exports.createAutocompletePlugin = function createAutocompletePlugin(options, api) {
|
|
150
162
|
var debounceTimer = null;
|
|
151
163
|
var hasIngestedPage = false;
|
|
152
164
|
var resolvedContext;
|
|
@@ -163,6 +175,24 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
163
175
|
* re-showing the same suggestion. Resets to null as soon as the text changes.
|
|
164
176
|
*/
|
|
165
177
|
var dismissedContext = null;
|
|
178
|
+
var lastSuggestionTypedLength = 0;
|
|
179
|
+
var lastSuggestionLength = 0;
|
|
180
|
+
var fireSuggestionInsertedAnalytics = function fireSuggestionInsertedAnalytics(ghostText) {
|
|
181
|
+
var _api$analytics;
|
|
182
|
+
var typedLength = lastSuggestionTypedLength;
|
|
183
|
+
var suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
|
|
184
|
+
var kssDelta = suggestionLength - typedLength;
|
|
185
|
+
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
|
|
186
|
+
action: _analytics.ACTION.SUGGESTION_INSERTED,
|
|
187
|
+
actionSubject: _analytics.ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
188
|
+
eventType: _analytics.EVENT_TYPE.TRACK,
|
|
189
|
+
attributes: {
|
|
190
|
+
suggestionLength: suggestionLength,
|
|
191
|
+
typedLength: typedLength,
|
|
192
|
+
kssDelta: kssDelta
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
166
196
|
var slowLaneClient = (0, _slowLaneClient.createSlowLaneClient)({
|
|
167
197
|
baseUrl: '',
|
|
168
198
|
endpoint: SLOW_LANE_ENDPOINT
|
|
@@ -203,7 +233,19 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
203
233
|
// Tier 1 prediction is synchronous -- no async needed
|
|
204
234
|
var prediction = (0, _textPredictor.predict)(textBefore);
|
|
205
235
|
if (prediction && prediction.length > 0) {
|
|
236
|
+
var typedLength = getTypedLengthForPrediction(textBefore);
|
|
237
|
+
lastSuggestionTypedLength = typedLength;
|
|
238
|
+
lastSuggestionLength = typedLength + prediction.length;
|
|
206
239
|
showGhostText(view, prediction, selection.from);
|
|
240
|
+
if (prediction !== lastShownGhostText) {
|
|
241
|
+
var _api$analytics2;
|
|
242
|
+
lastShownGhostText = prediction;
|
|
243
|
+
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || _api$analytics2.actions.fireAnalyticsEvent({
|
|
244
|
+
action: _analytics.ACTION.SUGGESTION_VIEWED,
|
|
245
|
+
actionSubject: _analytics.ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
246
|
+
eventType: _analytics.EVENT_TYPE.TRACK
|
|
247
|
+
});
|
|
248
|
+
}
|
|
207
249
|
}
|
|
208
250
|
}, DEBOUNCE_MS);
|
|
209
251
|
};
|
|
@@ -274,13 +316,27 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
274
316
|
},
|
|
275
317
|
handleKeyDown: (0, _keymap.keydownHandler)({
|
|
276
318
|
Tab: function Tab(state, dispatch) {
|
|
319
|
+
var _pluginState$ghostTex;
|
|
320
|
+
var pluginState = autocompletePluginKey.getState(state);
|
|
321
|
+
var ghostText = (_pluginState$ghostTex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.ghostText) !== null && _pluginState$ghostTex !== void 0 ? _pluginState$ghostTex : '';
|
|
277
322
|
var accepted = acceptGhostText(state, dispatch);
|
|
278
|
-
if (accepted)
|
|
323
|
+
if (accepted) {
|
|
324
|
+
justAccepted = true;
|
|
325
|
+
lastShownGhostText = '';
|
|
326
|
+
fireSuggestionInsertedAnalytics(ghostText);
|
|
327
|
+
}
|
|
279
328
|
return accepted;
|
|
280
329
|
},
|
|
281
330
|
ArrowRight: function ArrowRight(state, dispatch) {
|
|
331
|
+
var _pluginState$ghostTex2;
|
|
332
|
+
var pluginState = autocompletePluginKey.getState(state);
|
|
333
|
+
var ghostText = (_pluginState$ghostTex2 = pluginState === null || pluginState === void 0 ? void 0 : pluginState.ghostText) !== null && _pluginState$ghostTex2 !== void 0 ? _pluginState$ghostTex2 : '';
|
|
282
334
|
var accepted = acceptGhostText(state, dispatch);
|
|
283
|
-
if (accepted)
|
|
335
|
+
if (accepted) {
|
|
336
|
+
justAccepted = true;
|
|
337
|
+
lastShownGhostText = '';
|
|
338
|
+
fireSuggestionInsertedAnalytics(ghostText);
|
|
339
|
+
}
|
|
284
340
|
return accepted;
|
|
285
341
|
},
|
|
286
342
|
Escape: function Escape(state, dispatch) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isAutocompleteDebugEnabled = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Contextual Typeahead Completions (CTC) debug logging utility.
|
|
9
|
+
*
|
|
10
|
+
* Logs are silent by default. To enable in any environment (dev, staging, prod):
|
|
11
|
+
*
|
|
12
|
+
* localStorage.setItem('atl-ctc-dbg', '1')
|
|
13
|
+
*
|
|
14
|
+
* Then reload the page. To disable:
|
|
15
|
+
*
|
|
16
|
+
* localStorage.removeItem('atl-ctc-dbg')
|
|
17
|
+
*/
|
|
18
|
+
var isAutocompleteDebugEnabled = exports.isAutocompleteDebugEnabled = function isAutocompleteDebugEnabled() {
|
|
19
|
+
try {
|
|
20
|
+
return typeof localStorage !== 'undefined' && localStorage.getItem('atl-ctc-dbg') === '1';
|
|
21
|
+
} catch (_unused) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -8,6 +8,7 @@ exports.setDefaultSlowLaneClient = exports.isWordBoundary = exports.getStoredLmL
|
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
10
10
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
11
|
+
var _debugMode = require("./debug-mode");
|
|
11
12
|
/**
|
|
12
13
|
* Slow Lane Client: Backend context encoding for autocomplete.
|
|
13
14
|
*
|
|
@@ -81,37 +82,41 @@ var createSlowLaneClient = exports.createSlowLaneClient = function createSlowLan
|
|
|
81
82
|
payload = {
|
|
82
83
|
text: text,
|
|
83
84
|
session_id: sessionId
|
|
84
|
-
};
|
|
85
|
-
|
|
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) {
|
|
85
|
+
};
|
|
86
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
88
87
|
// eslint-disable-next-line no-console
|
|
89
|
-
console.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
console.groupCollapsed("%c[SlowLane] %c\uD83D\uDCE4 Sending context | ".concat(text.length, " chars"), 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
|
|
89
|
+
text.split('\n').forEach(function (line, i, arr) {
|
|
90
|
+
// eslint-disable-next-line no-console
|
|
91
|
+
console.log(" ".concat(i === arr.length - 1 ? '▶' : ' ', " ").concat(line));
|
|
92
|
+
});
|
|
93
|
+
// eslint-disable-next-line no-console
|
|
94
|
+
console.groupEnd();
|
|
95
|
+
}
|
|
96
|
+
_context.prev = 5;
|
|
97
|
+
_context.next = 8;
|
|
95
98
|
return fetchFn(url, {
|
|
96
99
|
method: 'POST',
|
|
97
100
|
headers: headers,
|
|
98
101
|
body: JSON.stringify(payload)
|
|
99
102
|
});
|
|
100
|
-
case
|
|
103
|
+
case 8:
|
|
101
104
|
res = _context.sent;
|
|
102
105
|
if (res.ok) {
|
|
103
|
-
_context.next =
|
|
106
|
+
_context.next = 14;
|
|
104
107
|
break;
|
|
105
108
|
}
|
|
106
109
|
storedContextVector = null;
|
|
107
110
|
storedLmLogits = null;
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.log("%c[SlowLane] %c\u274C Request failed (".concat(res.status, ")"), 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
|
|
114
|
+
}
|
|
110
115
|
return _context.abrupt("return");
|
|
111
|
-
case
|
|
112
|
-
_context.next =
|
|
116
|
+
case 14:
|
|
117
|
+
_context.next = 16;
|
|
113
118
|
return res.json();
|
|
114
|
-
case
|
|
119
|
+
case 16:
|
|
115
120
|
data = _context.sent;
|
|
116
121
|
if (data.semantic_vector && Array.isArray(data.semantic_vector)) {
|
|
117
122
|
storedContextVector = new Float32Array(data.semantic_vector);
|
|
@@ -123,36 +128,38 @@ var createSlowLaneClient = exports.createSlowLaneClient = function createSlowLan
|
|
|
123
128
|
} else {
|
|
124
129
|
storedLmLogits = null;
|
|
125
130
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
132
|
+
// eslint-disable-next-line no-console
|
|
133
|
+
console.groupCollapsed("%c[SlowLane] %c\uD83D\uDCE5 Response received", 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
|
|
134
|
+
// eslint-disable-next-line no-console
|
|
135
|
+
console.log(storedContextVector ? "\u2705 semantic_vector: ".concat(storedContextVector.length, " dims") : '❌ No semantic_vector');
|
|
136
|
+
// eslint-disable-next-line no-console
|
|
137
|
+
console.log(storedLmLogits ? "\u2705 lm_logits: ".concat(Object.keys(storedLmLogits).length, " tokens") : '❌ No lm_logits');
|
|
138
|
+
// eslint-disable-next-line no-console
|
|
139
|
+
console.groupEnd();
|
|
140
|
+
}
|
|
136
141
|
onUpdate === null || onUpdate === void 0 || onUpdate({
|
|
137
142
|
textLength: text.length,
|
|
138
143
|
hasVector: storedContextVector !== null,
|
|
139
144
|
hasLmLogits: storedLmLogits !== null
|
|
140
145
|
});
|
|
141
146
|
// eslint-disable-next-line no-unused-vars
|
|
142
|
-
_context.next =
|
|
147
|
+
_context.next = 28;
|
|
143
148
|
break;
|
|
144
|
-
case
|
|
145
|
-
_context.prev =
|
|
146
|
-
_context.t0 = _context["catch"](
|
|
149
|
+
case 23:
|
|
150
|
+
_context.prev = 23;
|
|
151
|
+
_context.t0 = _context["catch"](5);
|
|
147
152
|
storedContextVector = null;
|
|
148
153
|
storedLmLogits = null;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
155
|
+
// eslint-disable-next-line no-console
|
|
156
|
+
console.log('%c[SlowLane] %c❌ Network error — context cleared', 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
|
|
157
|
+
}
|
|
158
|
+
case 28:
|
|
152
159
|
case "end":
|
|
153
160
|
return _context.stop();
|
|
154
161
|
}
|
|
155
|
-
}, _callee, null, [[
|
|
162
|
+
}, _callee, null, [[5, 23]]);
|
|
156
163
|
}));
|
|
157
164
|
return function doUpdateContext(_x) {
|
|
158
165
|
return _ref.apply(this, arguments);
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.
|
|
7
|
+
exports.predict = exports.loadVectorsAsync = exports.loadDefaultVocabulary = exports.initVocabulary = exports.initVectors = exports.initL3Vocabulary = exports.ingestDocumentPage = exports.incrementSessionFreq = exports.getPredictorStatus = exports.getLastPredictionDebug = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
10
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
@@ -14,6 +14,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
14
14
|
var _l3_vocabulary = _interopRequireDefault(require("./data/l3_vocabulary.json"));
|
|
15
15
|
var _vocabulary_10k = _interopRequireDefault(require("./data/vocabulary_10k.json"));
|
|
16
16
|
var _word_index_10k = _interopRequireDefault(require("./data/word_index_10k.json"));
|
|
17
|
+
var _debugMode = require("./debug-mode");
|
|
17
18
|
var _scoringPipeline = require("./scoring-pipeline");
|
|
18
19
|
var _slowLaneClient = require("./slow-lane-client");
|
|
19
20
|
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; } } }; }
|
|
@@ -226,7 +227,7 @@ var initL3Vocabulary = exports.initL3Vocabulary = function initL3Vocabulary(l3Wo
|
|
|
226
227
|
} finally {
|
|
227
228
|
_iterator5.f();
|
|
228
229
|
}
|
|
229
|
-
if (
|
|
230
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
230
231
|
// eslint-disable-next-line no-console
|
|
231
232
|
console.log("[text-predictor] L3 General English loaded: ".concat(l3Words.length, " words"));
|
|
232
233
|
}
|
|
@@ -239,9 +240,7 @@ var initL3Vocabulary = exports.initL3Vocabulary = function initL3Vocabulary(l3Wo
|
|
|
239
240
|
var isInitialized = false;
|
|
240
241
|
var vectorStore = null;
|
|
241
242
|
var vectorsLoadStarted = false;
|
|
242
|
-
var debugMode = true;
|
|
243
243
|
var lastPredictionDebug = null;
|
|
244
|
-
var hasLoggedSemanticActive = false;
|
|
245
244
|
|
|
246
245
|
/** Get vector for a word from the store. */
|
|
247
246
|
var getWordVector = function getWordVector(word) {
|
|
@@ -347,25 +346,12 @@ var extractPreviousWord = function extractPreviousWord(text) {
|
|
|
347
346
|
|
|
348
347
|
// ─── Debug Helpers ───────────────────────────────────────────────────────────
|
|
349
348
|
|
|
350
|
-
/** Enable or disable debug logging. Also checks localStorage key `autocomplete-debug`. */
|
|
351
|
-
var setDebugMode = exports.setDebugMode = function setDebugMode(enabled) {
|
|
352
|
-
debugMode = enabled;
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
/** Check localStorage for autocomplete-debug on first access. */
|
|
356
|
-
var ensureDebugModeFromStorage = function ensureDebugModeFromStorage() {
|
|
357
|
-
if (typeof localStorage !== 'undefined' && localStorage.getItem('autocomplete-debug') === '1') {
|
|
358
|
-
debugMode = true;
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
|
|
362
349
|
/**
|
|
363
350
|
* Get predictor status for debugging.
|
|
364
351
|
* vectorsLoaded: true when semantic scoring is active
|
|
365
352
|
* wordCount: number of words in vector store (0 if not loaded)
|
|
366
353
|
*/
|
|
367
354
|
var getPredictorStatus = exports.getPredictorStatus = function getPredictorStatus() {
|
|
368
|
-
ensureDebugModeFromStorage();
|
|
369
355
|
return {
|
|
370
356
|
vectorsLoaded: vectorStore !== null,
|
|
371
357
|
wordCount: vectorStore ? Object.keys(vectorStore.wordIndex).length : 0,
|
|
@@ -379,7 +365,6 @@ var getPredictorStatus = exports.getPredictorStatus = function getPredictorStatu
|
|
|
379
365
|
* Returns null if no prediction has run yet or debug was off.
|
|
380
366
|
*/
|
|
381
367
|
var getLastPredictionDebug = exports.getLastPredictionDebug = function getLastPredictionDebug() {
|
|
382
|
-
ensureDebugModeFromStorage();
|
|
383
368
|
return lastPredictionDebug;
|
|
384
369
|
};
|
|
385
370
|
var initVocabulary = exports.initVocabulary = function initVocabulary(vocabulary) {
|
|
@@ -438,7 +423,7 @@ var ingestDocumentPage = exports.ingestDocumentPage = function ingestDocumentPag
|
|
|
438
423
|
} finally {
|
|
439
424
|
_iterator9.f();
|
|
440
425
|
}
|
|
441
|
-
if (
|
|
426
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)() && validBoostedWords.size > 0) {
|
|
442
427
|
// eslint-disable-next-line no-console
|
|
443
428
|
console.groupCollapsed("%c[L1 Session] %cPrimed ".concat(validBoostedWords.size, " valid dictionary words from page"), 'color: #00b8d9; font-weight: bold;', 'color: inherit; font-style: italic;');
|
|
444
429
|
// eslint-disable-next-line no-console
|
|
@@ -448,7 +433,6 @@ var ingestDocumentPage = exports.ingestDocumentPage = function ingestDocumentPag
|
|
|
448
433
|
}
|
|
449
434
|
};
|
|
450
435
|
var predict = exports.predict = function predict(textBefore) {
|
|
451
|
-
ensureDebugModeFromStorage();
|
|
452
436
|
if (!isInitialized) {
|
|
453
437
|
loadDefaultVocabulary();
|
|
454
438
|
}
|
|
@@ -541,7 +525,7 @@ var predict = exports.predict = function predict(textBefore) {
|
|
|
541
525
|
var lmLogits = (0, _slowLaneClient.getStoredLmLogits)();
|
|
542
526
|
|
|
543
527
|
// Raw LM Output Logger
|
|
544
|
-
if (
|
|
528
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)() && lmLogits && Object.keys(lmLogits).length > 0) {
|
|
545
529
|
var rawLmTop = Object.entries(lmLogits).sort(function (a, b) {
|
|
546
530
|
return b[1] - a[1];
|
|
547
531
|
}).slice(0, 5).map(function (_ref) {
|
|
@@ -557,9 +541,6 @@ var predict = exports.predict = function predict(textBefore) {
|
|
|
557
541
|
console.log('%c[Raw LM Prediction]🧠', 'color: #e83e8c; font-weight: bold;', rawLmTop);
|
|
558
542
|
}
|
|
559
543
|
var mode = contextVector ? 'warm' : 'cold';
|
|
560
|
-
if (debugMode && contextVector && !hasLoggedSemanticActive) {
|
|
561
|
-
hasLoggedSemanticActive = true;
|
|
562
|
-
}
|
|
563
544
|
|
|
564
545
|
// Build ScoringCandidate array from TrieNodes
|
|
565
546
|
var scoringCandidates = candidates.map(function (_ref3) {
|
|
@@ -590,7 +571,7 @@ var predict = exports.predict = function predict(textBefore) {
|
|
|
590
571
|
pipelineDebug = _rankCandidates.pipelineDebug;
|
|
591
572
|
var best = ranked[0];
|
|
592
573
|
var suggestion = best && best.finalScore >= MIN_SCORE_THRESHOLD ? best.word.slice(currentWord.length) : null;
|
|
593
|
-
if (
|
|
574
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
594
575
|
var latencyMs = performance.now() - t0;
|
|
595
576
|
var tokens = tokenize(trimmed);
|
|
596
577
|
var contextWords = tokens.slice(-CONTEXT_WORDS);
|
|
@@ -770,8 +751,7 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
770
751
|
wordIndex: wordIndex,
|
|
771
752
|
dim: dim
|
|
772
753
|
};
|
|
773
|
-
|
|
774
|
-
if (debugMode) {
|
|
754
|
+
if ((0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
775
755
|
// eslint-disable-next-line no-console
|
|
776
756
|
console.log('[text-predictor] Vectors loaded:', {
|
|
777
757
|
wordCount: nWords,
|
|
@@ -779,19 +759,19 @@ var loadVectorsAsync = exports.loadVectorsAsync = /*#__PURE__*/function () {
|
|
|
779
759
|
sizeBytes: float32.byteLength
|
|
780
760
|
});
|
|
781
761
|
}
|
|
782
|
-
_context.next =
|
|
762
|
+
_context.next = 40;
|
|
783
763
|
break;
|
|
784
|
-
case
|
|
785
|
-
_context.prev =
|
|
764
|
+
case 36:
|
|
765
|
+
_context.prev = 36;
|
|
786
766
|
_context.t1 = _context["catch"](17);
|
|
787
767
|
vectorsLoadStarted = false;
|
|
788
768
|
// eslint-disable-next-line no-console
|
|
789
769
|
console.warn('[text-predictor] Failed to load vectors:', _context.t1);
|
|
790
|
-
case
|
|
770
|
+
case 40:
|
|
791
771
|
case "end":
|
|
792
772
|
return _context.stop();
|
|
793
773
|
}
|
|
794
|
-
}, _callee, null, [[6, 12], [17,
|
|
774
|
+
}, _callee, null, [[6, 12], [17, 36]]);
|
|
795
775
|
}));
|
|
796
776
|
return function loadVectorsAsync(_x) {
|
|
797
777
|
return _ref6.apply(this, arguments);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { autocompletePluginKey, createAutocompletePlugin } from './pm-plugins/autocomplete-plugin';
|
|
2
2
|
export const autocompletePlugin = ({
|
|
3
|
-
config: options
|
|
3
|
+
config: options,
|
|
4
|
+
api
|
|
4
5
|
}) => {
|
|
5
6
|
return {
|
|
6
7
|
name: 'autocomplete',
|
|
@@ -13,7 +14,7 @@ export const autocompletePlugin = ({
|
|
|
13
14
|
pmPlugins() {
|
|
14
15
|
return [{
|
|
15
16
|
name: 'autocomplete',
|
|
16
|
-
plugin: () => createAutocompletePlugin(options)
|
|
17
|
+
plugin: () => createAutocompletePlugin(options, api)
|
|
17
18
|
}];
|
|
18
19
|
}
|
|
19
20
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
1
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
3
|
import { keydownHandler } from '@atlaskit/editor-prosemirror/keymap';
|
|
3
4
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
@@ -58,6 +59,7 @@ const setAutocompleteMeta = (tr, meta) => {
|
|
|
58
59
|
/**
|
|
59
60
|
* Apply a ghost text suggestion to the editor state.
|
|
60
61
|
*/
|
|
62
|
+
let lastShownGhostText = '';
|
|
61
63
|
const showGhostText = (view, text, position) => {
|
|
62
64
|
const {
|
|
63
65
|
state,
|
|
@@ -140,7 +142,17 @@ const buildSlowLaneText = (docText, context) => {
|
|
|
140
142
|
lines.push(`reply ${nextReplyNumber}: ${docText}`);
|
|
141
143
|
return lines.join('\n');
|
|
142
144
|
};
|
|
143
|
-
|
|
145
|
+
const getTypedLengthForPrediction = textBefore => {
|
|
146
|
+
var _textBefore$match$, _textBefore$match;
|
|
147
|
+
if (isWordBoundary(textBefore)) {
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
152
|
+
const trailingToken = (_textBefore$match$ = (_textBefore$match = textBefore.match(/([^\s.,;:!?]*)$/)) === null || _textBefore$match === void 0 ? void 0 : _textBefore$match[1]) !== null && _textBefore$match$ !== void 0 ? _textBefore$match$ : '';
|
|
153
|
+
return trailingToken.length;
|
|
154
|
+
};
|
|
155
|
+
export const createAutocompletePlugin = (options, api) => {
|
|
144
156
|
let debounceTimer = null;
|
|
145
157
|
let hasIngestedPage = false;
|
|
146
158
|
let resolvedContext;
|
|
@@ -157,6 +169,24 @@ export const createAutocompletePlugin = options => {
|
|
|
157
169
|
* re-showing the same suggestion. Resets to null as soon as the text changes.
|
|
158
170
|
*/
|
|
159
171
|
let dismissedContext = null;
|
|
172
|
+
let lastSuggestionTypedLength = 0;
|
|
173
|
+
let lastSuggestionLength = 0;
|
|
174
|
+
const fireSuggestionInsertedAnalytics = ghostText => {
|
|
175
|
+
var _api$analytics;
|
|
176
|
+
const typedLength = lastSuggestionTypedLength;
|
|
177
|
+
const suggestionLength = lastSuggestionLength || typedLength + ghostText.length;
|
|
178
|
+
const kssDelta = suggestionLength - typedLength;
|
|
179
|
+
api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent({
|
|
180
|
+
action: ACTION.SUGGESTION_INSERTED,
|
|
181
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
182
|
+
eventType: EVENT_TYPE.TRACK,
|
|
183
|
+
attributes: {
|
|
184
|
+
suggestionLength,
|
|
185
|
+
typedLength,
|
|
186
|
+
kssDelta
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
};
|
|
160
190
|
const slowLaneClient = createSlowLaneClient({
|
|
161
191
|
baseUrl: '',
|
|
162
192
|
endpoint: SLOW_LANE_ENDPOINT
|
|
@@ -201,7 +231,19 @@ export const createAutocompletePlugin = options => {
|
|
|
201
231
|
// Tier 1 prediction is synchronous -- no async needed
|
|
202
232
|
const prediction = predict(textBefore);
|
|
203
233
|
if (prediction && prediction.length > 0) {
|
|
234
|
+
const typedLength = getTypedLengthForPrediction(textBefore);
|
|
235
|
+
lastSuggestionTypedLength = typedLength;
|
|
236
|
+
lastSuggestionLength = typedLength + prediction.length;
|
|
204
237
|
showGhostText(view, prediction, selection.from);
|
|
238
|
+
if (prediction !== lastShownGhostText) {
|
|
239
|
+
var _api$analytics2;
|
|
240
|
+
lastShownGhostText = prediction;
|
|
241
|
+
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.fireAnalyticsEvent({
|
|
242
|
+
action: ACTION.SUGGESTION_VIEWED,
|
|
243
|
+
actionSubject: ACTION_SUBJECT.CONTEXTUAL_TYPEAHEAD,
|
|
244
|
+
eventType: EVENT_TYPE.TRACK
|
|
245
|
+
});
|
|
246
|
+
}
|
|
205
247
|
}
|
|
206
248
|
}, DEBOUNCE_MS);
|
|
207
249
|
};
|
|
@@ -275,13 +317,27 @@ export const createAutocompletePlugin = options => {
|
|
|
275
317
|
},
|
|
276
318
|
handleKeyDown: keydownHandler({
|
|
277
319
|
Tab: (state, dispatch) => {
|
|
320
|
+
var _pluginState$ghostTex;
|
|
321
|
+
const pluginState = autocompletePluginKey.getState(state);
|
|
322
|
+
const ghostText = (_pluginState$ghostTex = pluginState === null || pluginState === void 0 ? void 0 : pluginState.ghostText) !== null && _pluginState$ghostTex !== void 0 ? _pluginState$ghostTex : '';
|
|
278
323
|
const accepted = acceptGhostText(state, dispatch);
|
|
279
|
-
if (accepted)
|
|
324
|
+
if (accepted) {
|
|
325
|
+
justAccepted = true;
|
|
326
|
+
lastShownGhostText = '';
|
|
327
|
+
fireSuggestionInsertedAnalytics(ghostText);
|
|
328
|
+
}
|
|
280
329
|
return accepted;
|
|
281
330
|
},
|
|
282
331
|
ArrowRight: (state, dispatch) => {
|
|
332
|
+
var _pluginState$ghostTex2;
|
|
333
|
+
const pluginState = autocompletePluginKey.getState(state);
|
|
334
|
+
const ghostText = (_pluginState$ghostTex2 = pluginState === null || pluginState === void 0 ? void 0 : pluginState.ghostText) !== null && _pluginState$ghostTex2 !== void 0 ? _pluginState$ghostTex2 : '';
|
|
283
335
|
const accepted = acceptGhostText(state, dispatch);
|
|
284
|
-
if (accepted)
|
|
336
|
+
if (accepted) {
|
|
337
|
+
justAccepted = true;
|
|
338
|
+
lastShownGhostText = '';
|
|
339
|
+
fireSuggestionInsertedAnalytics(ghostText);
|
|
340
|
+
}
|
|
285
341
|
return accepted;
|
|
286
342
|
},
|
|
287
343
|
Escape: (state, dispatch) => {
|
|
@@ -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 = () => {
|
|
13
|
+
try {
|
|
14
|
+
return typeof localStorage !== 'undefined' && localStorage.getItem('atl-ctc-dbg') === '1';
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
};
|