@atlaskit/editor-plugin-autocomplete 9.0.0 → 9.1.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 +28 -0
- package/dist/cjs/pm-plugins/autocomplete-plugin.js +82 -31
- package/dist/cjs/pm-plugins/debug-mode.js +17 -2
- package/dist/cjs/pm-plugins/text-predictor.js +290 -178
- package/dist/es2019/pm-plugins/autocomplete-plugin.js +64 -22
- package/dist/es2019/pm-plugins/debug-mode.js +16 -1
- package/dist/es2019/pm-plugins/text-predictor.js +91 -3
- package/dist/esm/pm-plugins/autocomplete-plugin.js +82 -31
- package/dist/esm/pm-plugins/debug-mode.js +16 -1
- package/dist/esm/pm-plugins/text-predictor.js +290 -178
- package/dist/types/pm-plugins/debug-mode.d.ts +19 -0
- package/dist/types/pm-plugins/text-predictor.d.ts +36 -1
- package/package.json +2 -2
- package/src/pm-plugins/autocomplete-plugin.ts +67 -21
- package/src/pm-plugins/debug-mode.ts +26 -1
- package/src/pm-plugins/text-predictor.ts +116 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-autocomplete
|
|
2
2
|
|
|
3
|
+
## 9.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`a164c6d8e7de6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a164c6d8e7de6) -
|
|
8
|
+
Offer the Confluence page the chat is open on to autocomplete as context, so words already written
|
|
9
|
+
on it carry an L1 session boost in the chat input. This reads the editor context the page editor
|
|
10
|
+
already publishes, so no host wiring is needed, and covers a page being edited; reaching a page
|
|
11
|
+
that is being viewed needs a host bridge that comes separately. The page text is held together
|
|
12
|
+
with the page it was read from, so navigating invalidates it in the same render that changes the
|
|
13
|
+
page rather than just after — the context store keeps the last published document until another
|
|
14
|
+
publisher replaces it, and that document does not say which page it came from.
|
|
15
|
+
|
|
16
|
+
Both the page and the chat transcript sit behind
|
|
17
|
+
`platform_editor_ai_autocomplete_rovo_chat_editor`, and the editor context subscription that reads
|
|
18
|
+
the page lives in a component the chat input only mounts once enrolled. An unenrolled session
|
|
19
|
+
therefore neither parses a page document for context it cannot use nor re-renders the input on a
|
|
20
|
+
publish, which the editor does on blur and on selection change.
|
|
21
|
+
|
|
22
|
+
Context text now waits for the vocabulary load to settle before it is applied. Session boosts were
|
|
23
|
+
previously spent against an empty trie whenever the page resolved first, which silently dropped
|
|
24
|
+
every word in it. What the session holds is readable from the console with
|
|
25
|
+
`__atlCtcDebug__.session()`.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies
|
|
30
|
+
|
|
3
31
|
## 9.0.0
|
|
4
32
|
|
|
5
33
|
### Major Changes
|
|
@@ -516,7 +516,72 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
516
516
|
// Set when the plugin is torn down so in-flight getContext() resolutions don't
|
|
517
517
|
// mutate the global text-predictor state after destruction.
|
|
518
518
|
var destroyed = false;
|
|
519
|
-
|
|
519
|
+
// L1 ingestion cannot run before the vocabulary has loaded: `incrementSessionFreq`
|
|
520
|
+
// only touches trie nodes that already exist, so an empty trie silently rejects
|
|
521
|
+
// every word. Text that arrives first — which a page usually does, since the
|
|
522
|
+
// chat resolves it on focus in the same tick as the load starts — is held here
|
|
523
|
+
// and applied once the load has settled.
|
|
524
|
+
var pendingSessionContextTexts = new Set();
|
|
525
|
+
var sessionIngestedContextTexts = new Set();
|
|
526
|
+
var isVocabularyReady = false;
|
|
527
|
+
var vocabularyLoadPromise;
|
|
528
|
+
var addBoundedContextText = function addBoundedContextText(texts, text) {
|
|
529
|
+
texts.add(text);
|
|
530
|
+
// Evict oldest entries (Set preserves insertion order) to bound memory.
|
|
531
|
+
while (texts.size > MAX_INGESTED_CONTEXT_TEXTS) {
|
|
532
|
+
var oldest = texts.values().next().value;
|
|
533
|
+
if (oldest === undefined) {
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
texts.delete(oldest);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
var flushPendingSessionContext = function flushPendingSessionContext() {
|
|
540
|
+
if (!isVocabularyReady || destroyed) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
var _iterator = _createForOfIteratorHelper(pendingSessionContextTexts),
|
|
544
|
+
_step;
|
|
545
|
+
try {
|
|
546
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
547
|
+
var text = _step.value;
|
|
548
|
+
if (!sessionIngestedContextTexts.has(text)) {
|
|
549
|
+
(0, _textPredictor.ingestDocumentPage)(text);
|
|
550
|
+
addBoundedContextText(sessionIngestedContextTexts, text);
|
|
551
|
+
}
|
|
552
|
+
pendingSessionContextTexts.delete(text);
|
|
553
|
+
}
|
|
554
|
+
} catch (err) {
|
|
555
|
+
_iterator.e(err);
|
|
556
|
+
} finally {
|
|
557
|
+
_iterator.f();
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
var ensureVocabularyReady = function ensureVocabularyReady() {
|
|
561
|
+
var _options$useLocalMode;
|
|
562
|
+
if (isVocabularyReady) {
|
|
563
|
+
flushPendingSessionContext();
|
|
564
|
+
return Promise.resolve();
|
|
565
|
+
}
|
|
566
|
+
vocabularyLoadPromise !== null && vocabularyLoadPromise !== void 0 ? vocabularyLoadPromise : vocabularyLoadPromise = (0, _textPredictor.loadDefaultVocabulary)({
|
|
567
|
+
isLocalLLM: (_options$useLocalMode = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode !== void 0 ? _options$useLocalMode : false,
|
|
568
|
+
surface: surface
|
|
569
|
+
}).then(function () {
|
|
570
|
+
if (destroyed) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
isVocabularyReady = true;
|
|
574
|
+
flushPendingSessionContext();
|
|
575
|
+
}).catch(function (error) {
|
|
576
|
+
// Do not consume the pending text on failure. A later focus retries the
|
|
577
|
+
// load and can still apply the original context exactly once.
|
|
578
|
+
vocabularyLoadPromise = undefined;
|
|
579
|
+
(0, _monitoring.logException)(error, {
|
|
580
|
+
location: 'editor-plugin-autocomplete/loadDefaultVocabulary'
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
return vocabularyLoadPromise;
|
|
584
|
+
};
|
|
520
585
|
var logContextResolved = function logContextResolved(source, context) {
|
|
521
586
|
var _context$parentCommen, _context$siblingComme4, _context$siblingComme5;
|
|
522
587
|
if (!(0, _debugMode.isAutocompleteDebugEnabled)()) {
|
|
@@ -546,37 +611,29 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
546
611
|
}));
|
|
547
612
|
resolvedContext = _objectSpread(_objectSpread({}, resolvedContext), definedContext);
|
|
548
613
|
var ingestContextText = function ingestContextText(text) {
|
|
549
|
-
if (!text ||
|
|
614
|
+
if (!text || sessionIngestedContextTexts.has(text)) {
|
|
550
615
|
return;
|
|
551
616
|
}
|
|
552
|
-
|
|
553
|
-
// Evict oldest entries (Set preserves insertion order) to bound memory.
|
|
554
|
-
while (ingestedContextTexts.size > MAX_INGESTED_CONTEXT_TEXTS) {
|
|
555
|
-
var oldest = ingestedContextTexts.values().next().value;
|
|
556
|
-
if (oldest === undefined) {
|
|
557
|
-
break;
|
|
558
|
-
}
|
|
559
|
-
ingestedContextTexts.delete(oldest);
|
|
560
|
-
}
|
|
561
|
-
(0, _textPredictor.ingestDocumentPage)(text);
|
|
617
|
+
addBoundedContextText(pendingSessionContextTexts, text);
|
|
562
618
|
};
|
|
563
619
|
ingestContextText(context.fullPageContent);
|
|
564
620
|
ingestContextText(context.parentCommentContent);
|
|
565
|
-
var
|
|
566
|
-
|
|
621
|
+
var _iterator2 = _createForOfIteratorHelper((_context$siblingComme6 = context.siblingCommentsContents) !== null && _context$siblingComme6 !== void 0 ? _context$siblingComme6 : []),
|
|
622
|
+
_step2;
|
|
567
623
|
try {
|
|
568
|
-
for (
|
|
569
|
-
var siblingCommentContent =
|
|
624
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
625
|
+
var siblingCommentContent = _step2.value;
|
|
570
626
|
ingestContextText(siblingCommentContent);
|
|
571
627
|
}
|
|
572
|
-
|
|
573
|
-
// Context arrived after word boundaries may already have fired. Re-send
|
|
574
|
-
// slow-lane context immediately so the next inference includes the thread.
|
|
575
628
|
} catch (err) {
|
|
576
|
-
|
|
629
|
+
_iterator2.e(err);
|
|
577
630
|
} finally {
|
|
578
|
-
|
|
631
|
+
_iterator2.f();
|
|
579
632
|
}
|
|
633
|
+
flushPendingSessionContext();
|
|
634
|
+
|
|
635
|
+
// Context arrived after word boundaries may already have fired. Re-send
|
|
636
|
+
// slow-lane context immediately so the next inference includes the thread.
|
|
580
637
|
if (currentView) {
|
|
581
638
|
slowLaneClient.updateContext(buildSlowLaneText(currentView.state.doc.textContent, resolvedContext));
|
|
582
639
|
}
|
|
@@ -967,18 +1024,11 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
967
1024
|
return accepted;
|
|
968
1025
|
},
|
|
969
1026
|
focus: function focus() {
|
|
970
|
-
var _options$
|
|
1027
|
+
var _options$useLocalMode2, _options$useLocalMode3;
|
|
971
1028
|
if (!isAutocompleteEnabled) {
|
|
972
1029
|
return false;
|
|
973
1030
|
}
|
|
974
|
-
(
|
|
975
|
-
isLocalLLM: (_options$useLocalMode = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode !== void 0 ? _options$useLocalMode : false,
|
|
976
|
-
surface: surface
|
|
977
|
-
}).catch(function (error) {
|
|
978
|
-
(0, _monitoring.logException)(error, {
|
|
979
|
-
location: 'editor-plugin-autocomplete/loadDefaultVocabulary'
|
|
980
|
-
});
|
|
981
|
-
});
|
|
1031
|
+
void ensureVocabularyReady();
|
|
982
1032
|
(0, _textPredictor.loadVectorsAsync)({
|
|
983
1033
|
isLocalLLM: (_options$useLocalMode2 = options === null || options === void 0 ? void 0 : options.useLocalModel) !== null && _options$useLocalMode2 !== void 0 ? _options$useLocalMode2 : false,
|
|
984
1034
|
surface: surface
|
|
@@ -1076,7 +1126,8 @@ var createAutocompletePlugin = exports.createAutocompletePlugin = function creat
|
|
|
1076
1126
|
if (hasDestroy(slowLaneClient)) {
|
|
1077
1127
|
slowLaneClient.destroy();
|
|
1078
1128
|
}
|
|
1079
|
-
|
|
1129
|
+
pendingSessionContextTexts.clear();
|
|
1130
|
+
sessionIngestedContextTexts.clear();
|
|
1080
1131
|
}
|
|
1081
1132
|
};
|
|
1082
1133
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.isAutocompleteDebugVerbose = exports.isAutocompleteDebugEnabled = exports.ctcTag = exports.ctcSection = exports.CTC_STYLES = void 0;
|
|
6
|
+
exports.registerCtcSessionInspector = exports.isAutocompleteDebugVerbose = exports.isAutocompleteDebugEnabled = exports.ctcTag = exports.ctcSection = exports.CTC_STYLES = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* Contextual Typeahead Completions (CTC) debug logging utility.
|
|
9
9
|
*
|
|
@@ -96,7 +96,7 @@ var printLegend = function printLegend(verbose) {
|
|
|
96
96
|
// eslint-disable-next-line no-console
|
|
97
97
|
console.log('%cPlanes%c [CTC:init] loads · [CTC:signal] semantic/network · [CTC:model] primes/exact · [CTC:model-cost] prefill/decode · [CTC:readiness] deadline progress', CTC_STYLES.section, CTC_STYLES.body);
|
|
98
98
|
// eslint-disable-next-line no-console
|
|
99
|
-
console.log('%cInspect%c __atlCtcDebug__.enable("verbose") · .disable()', CTC_STYLES.section, CTC_STYLES.body);
|
|
99
|
+
console.log('%cInspect%c __atlCtcDebug__.enable("verbose") · .disable() · .session() (L1 boosts, narrow to a family with .session("poll"))', CTC_STYLES.section, CTC_STYLES.body);
|
|
100
100
|
// eslint-disable-next-line no-console
|
|
101
101
|
console.groupEnd();
|
|
102
102
|
};
|
|
@@ -144,5 +144,20 @@ var isAutocompleteDebugVerbose = exports.isAutocompleteDebugVerbose = function i
|
|
|
144
144
|
return (_getDebugApi$isVerbos = (_getDebugApi2 = getDebugApi()) === null || _getDebugApi2 === void 0 ? void 0 : _getDebugApi2.isVerbose()) !== null && _getDebugApi$isVerbos !== void 0 ? _getDebugApi$isVerbos : false;
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Hang the L1 session-boost snapshot off the console API.
|
|
149
|
+
*
|
|
150
|
+
* Unlike the log helpers this is available whether or not debug is enabled:
|
|
151
|
+
* inspecting state on demand is not logging, and asking someone to turn on
|
|
152
|
+
* logging and retype to find out what the session already holds defeats the
|
|
153
|
+
* point of being able to ask.
|
|
154
|
+
*/
|
|
155
|
+
var registerCtcSessionInspector = exports.registerCtcSessionInspector = function registerCtcSessionInspector(inspect) {
|
|
156
|
+
var api = getDebugApi();
|
|
157
|
+
if (api) {
|
|
158
|
+
api.session = inspect;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
147
162
|
// Eagerly install so the console API is available on load, regardless of call order.
|
|
148
163
|
getDebugApi();
|