@atlaskit/editor-plugin-autocomplete 7.0.0 → 9.0.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 (80) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/compass.yml +2 -2
  3. package/dist/cjs/analytics/ufo.js +2 -1
  4. package/dist/cjs/pm-plugins/artifact-loader.js +135 -0
  5. package/dist/cjs/pm-plugins/artifacts-manifest.js +3 -0
  6. package/dist/cjs/pm-plugins/autocomplete-plugin.js +416 -129
  7. package/dist/cjs/pm-plugins/canonical-lm-scoring.js +371 -0
  8. package/dist/cjs/pm-plugins/debug-mode.js +90 -7
  9. package/dist/cjs/pm-plugins/ghost-text-decoration.js +12 -3
  10. package/dist/cjs/pm-plugins/local-slow-lane-client.js +1202 -453
  11. package/dist/cjs/pm-plugins/scoring-pipeline.js +164 -19
  12. package/dist/cjs/pm-plugins/slow-lane-client.js +100 -37
  13. package/dist/cjs/pm-plugins/text-predictor.js +1951 -273
  14. package/dist/es2019/analytics/ufo.js +2 -0
  15. package/dist/es2019/pm-plugins/artifact-loader.js +70 -0
  16. package/dist/es2019/pm-plugins/artifacts-manifest.js +3 -0
  17. package/dist/es2019/pm-plugins/autocomplete-plugin.js +425 -130
  18. package/dist/es2019/pm-plugins/canonical-lm-scoring.js +270 -0
  19. package/dist/es2019/pm-plugins/debug-mode.js +87 -7
  20. package/dist/es2019/pm-plugins/ghost-text-decoration.js +12 -3
  21. package/dist/es2019/pm-plugins/local-slow-lane-client.js +940 -326
  22. package/dist/es2019/pm-plugins/scoring-pipeline.js +137 -13
  23. package/dist/es2019/pm-plugins/slow-lane-client.js +94 -37
  24. package/dist/es2019/pm-plugins/text-predictor.js +1603 -199
  25. package/dist/esm/analytics/ufo.js +2 -1
  26. package/dist/esm/pm-plugins/artifact-loader.js +128 -0
  27. package/dist/esm/pm-plugins/artifacts-manifest.js +3 -0
  28. package/dist/esm/pm-plugins/autocomplete-plugin.js +419 -132
  29. package/dist/esm/pm-plugins/canonical-lm-scoring.js +364 -0
  30. package/dist/esm/pm-plugins/debug-mode.js +89 -6
  31. package/dist/esm/pm-plugins/ghost-text-decoration.js +12 -3
  32. package/dist/esm/pm-plugins/local-slow-lane-client.js +1200 -451
  33. package/dist/esm/pm-plugins/scoring-pipeline.js +163 -18
  34. package/dist/esm/pm-plugins/slow-lane-client.js +100 -37
  35. package/dist/esm/pm-plugins/text-predictor.js +1953 -277
  36. package/dist/types/analytics/ufo.d.ts +1 -0
  37. package/dist/types/pm-plugins/artifact-loader.d.ts +44 -0
  38. package/dist/types/pm-plugins/artifacts-manifest.d.ts +3 -0
  39. package/dist/types/pm-plugins/autocomplete-plugin.d.ts +39 -0
  40. package/dist/types/pm-plugins/canonical-lm-scoring.d.ts +158 -0
  41. package/dist/types/pm-plugins/debug-mode.d.ts +36 -1
  42. package/dist/types/pm-plugins/ghost-text-decoration.d.ts +5 -2
  43. package/dist/types/pm-plugins/local-slow-lane-client.d.ts +87 -54
  44. package/dist/types/pm-plugins/scoring-pipeline.d.ts +33 -1
  45. package/dist/types/pm-plugins/slow-lane-client.d.ts +51 -3
  46. package/dist/types/pm-plugins/text-predictor.d.ts +120 -2
  47. package/package.json +3 -3
  48. package/src/analytics/ufo.ts +5 -0
  49. package/src/pm-plugins/artifact-loader.ts +92 -0
  50. package/src/pm-plugins/artifacts-manifest.ts +3 -0
  51. package/src/pm-plugins/autocomplete-plugin.ts +517 -133
  52. package/src/pm-plugins/canonical-lm-scoring.ts +412 -0
  53. package/src/pm-plugins/debug-mode.ts +109 -7
  54. package/src/pm-plugins/ghost-text-decoration.ts +13 -4
  55. package/src/pm-plugins/local-slow-lane-client.ts +1302 -386
  56. package/src/pm-plugins/scoring-pipeline.ts +167 -17
  57. package/src/pm-plugins/slow-lane-client.ts +147 -62
  58. package/src/pm-plugins/text-predictor.ts +2006 -253
  59. package/CANONICAL_FIX__DO_NOT_USE_ME_A/package.json +0 -8
  60. package/CANONICAL_FIX__DO_NOT_USE_ME_B/package.json +0 -8
  61. package/CANONICAL_FIX__DO_NOT_USE_ME_C/package.json +0 -8
  62. package/dist/cjs/entry-points/src-pm-plugins-autocomplete-plugin.js +0 -18
  63. package/dist/cjs/entry-points/src-pm-plugins-slow-lane-client.js +0 -36
  64. package/dist/cjs/entry-points/src-pm-plugins-text-predictor.js +0 -66
  65. package/dist/es2019/entry-points/src-pm-plugins-autocomplete-plugin.js +0 -2
  66. package/dist/es2019/entry-points/src-pm-plugins-slow-lane-client.js +0 -2
  67. package/dist/es2019/entry-points/src-pm-plugins-text-predictor.js +0 -2
  68. package/dist/esm/entry-points/src-pm-plugins-autocomplete-plugin.js +0 -2
  69. package/dist/esm/entry-points/src-pm-plugins-slow-lane-client.js +0 -2
  70. package/dist/esm/entry-points/src-pm-plugins-text-predictor.js +0 -2
  71. package/dist/types/entry-points/src-pm-plugins-autocomplete-plugin.d.ts +0 -2
  72. package/dist/types/entry-points/src-pm-plugins-slow-lane-client.d.ts +0 -2
  73. package/dist/types/entry-points/src-pm-plugins-text-predictor.d.ts +0 -2
  74. package/scripts/gen_first_token_to_words.py +0 -170
  75. package/src/entry-points/src-pm-plugins-autocomplete-plugin.ts +0 -7
  76. package/src/entry-points/src-pm-plugins-slow-lane-client.ts +0 -13
  77. package/src/entry-points/src-pm-plugins-text-predictor.ts +0 -14
  78. package/src/pm-plugins/autocomplete-plugin/package.json +0 -8
  79. package/src/pm-plugins/slow-lane-client/package.json +0 -8
  80. package/src/pm-plugins/text-predictor/package.json +0 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,91 @@
1
1
  # @atlaskit/editor-plugin-autocomplete
2
2
 
3
+ ## 9.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`94ddcfaca6b5d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/94ddcfaca6b5d) -
8
+ Improve client-only contextual typeahead confidence and responsiveness, and extend it to bigram
9
+ and phrase completions.
10
+
11
+ All of this ships inside the autocomplete plugin, which is only ever added to a preset behind an
12
+ experiment that defaults to off: `platform_editor_ai_autocomplete_rovo_chat_editor` for Rovo chat,
13
+ with a Confluence `productKey` check ahead of the read, and
14
+ `platform_editor_ai_autocomplete_conf_comments` for Confluence comments. The on-device model path
15
+ these changes concentrate on is additionally behind
16
+ `platform_editor_ai_autocomplete_conf_local_setup`, which selects the slow-lane client. With those
17
+ experiments off the plugin is never constructed, so nothing here runs.
18
+
19
+ **Confidence.** Candidates competing at the same word boundary are normalised into a posterior
20
+ over that shortlist, so a suggestion's confidence is the share of probability mass the model puts
21
+ on it rather than its distance from whichever candidate happens to lead. The comparison is made on
22
+ each surface's sequence log-likelihood rather than its per-token mean, which is not comparable
23
+ across surfaces of different token counts. A shortlist is normalised over its minimal members
24
+ only, so a surface and its own extension are no longer double-counted. A surface must additionally
25
+ clear an absolute plausibility floor, anchored at the uniform distribution over the model's
26
+ 49,152-token vocabulary (about -10.8 nats) rather than read off a histogram, hold a clear lead
27
+ over the runner-up, and come from a shortlist that offered a real alternative. Completions shorter
28
+ than three characters are no longer offered, and multi-word terms are held to the same
29
+ previous-word grammar transition as single words.
30
+
31
+ **Responsiveness.** Candidate work starts at two typed characters while ghost text stays gated at
32
+ three and must arrive within a 100 ms decision window. Queued scoring work is drained in an order
33
+ that keeps the engine's decoded sequence alive, so continuing a prefix costs a single decode step
34
+ instead of a full prompt prefill, and work no live decision would accept is discarded rather than
35
+ run. Contexts keep their prefilled model state until 128 are resident rather than 32, which stops
36
+ contexts being evicted while still in use. Once displayed, a ghost is an immutable snapshot shared
37
+ by rendering, Tab insertion, analytics and cooldown, so a later model result cannot make the
38
+ visible completion disagree with the inserted one.
39
+
40
+ **Per-keystroke cost.** One keystroke runs `predict()` several times — once when the decision
41
+ opens and again for each async evidence signal that lands inside the budget — and only the
42
+ evidence differs between those runs. Trie recall and the canonical context derived per candidate
43
+ are computed once and reused across them, invalidated when an artifact load changes what the tries
44
+ can return. Within one derivation the position-dependent half of a candidate's context is shared
45
+ by every candidate starting at the same offset, rather than being rebuilt a couple of hundred
46
+ times. A distribution's log-partition is memoised per logits buffer, since it does not depend on
47
+ the token being scored and the two full-vocabulary passes behind it previously ran once per
48
+ candidate for an answer that could not change. None of this changes which suggestion is chosen.
49
+
50
+ **Multi-word completions.** Bigrams and phrases are surfaced from a first-word or in-progress
51
+ window, frequency is normalised per term type, and selection runs a per-type precision floor
52
+ followed by expected-value arbitration, so the longest confident unit wins and a shaky long unit
53
+ self-demotes to a safer shorter one. Phrases surface only once the on-device continuation LM has
54
+ vouched for them. A whole-surface repetition guard and a post-accept cooldown together prevent
55
+ echoes such as `end to end` becoming `end to end to end`.
56
+
57
+ **Artifacts.** `bigrams.json`, `phrases.json` and `phrase-continuation-tokens.json` are resolved
58
+ from the artifacts manifest alongside the vocabulary and grammar payloads, so they are served from
59
+ the CDN rather than bundled. Each is fetched independently, so an unpublished payload disables
60
+ only its own term type. Every artifact is shape-checked as it downloads, failing at the boundary
61
+ naming the artifact rather than degrading later into an empty trie.
62
+
63
+ **Diagnostics.** Debug output is unified under a single `[CTC]` namespace behind
64
+ `__atlCtcDebug__.enable()`, with one collapsed group per keystroke and an opt-in verbose level for
65
+ the scored candidate table. All informational console output is routed behind the flag.
66
+
67
+ **Breaking change.** `@atlaskit/editor-plugin-autocomplete` no longer exposes its pm-plugin
68
+ modules as subpaths. The `./src/pm-plugins/autocomplete-plugin`,
69
+ `./src/pm-plugins/slow-lane-client` and `./src/pm-plugins/text-predictor` entry points are
70
+ removed, along with the `CANONICAL_FIX__DO_NOT_USE_ME_A`, `_B` and `_C` subpaths that exposed the
71
+ same three modules in raw form. The matching `./autocomplete/*` re-export wrappers in
72
+ `@atlaskit/editor-plugins` are removed too. No product consumed any of them; they were reachable
73
+ only from this plugin's own test package and the generated aggregator.
74
+
75
+ Removing both sets together is deliberate. The curated subpaths were named after real file paths,
76
+ so each one shadowed the module it wrapped and left two files claiming the same bundler canonical
77
+ id — which is what the `CANONICAL_FIX` subpaths existed to disambiguate. Keeping either set alone
78
+ reintroduces the collision. With both gone, nothing shadows a source path, and because the
79
+ wrappers mirrored the raw modules under an exact export-parity test, `@atlaskit/editor-plugins` is
80
+ no longer coupled to this plugin's internal module layout. `./autocompletePlugin` and
81
+ `./autocompletePluginType` are unaffected.
82
+
83
+ ## 8.0.0
84
+
85
+ ### Patch Changes
86
+
87
+ - Updated dependencies
88
+
3
89
  ## 7.0.0
4
90
 
5
91
  ### Major Changes
package/compass.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  configVersion: 1
2
2
  id: ari:cloud:compass:a436116f-02ce-4520-8fbb-7301462a1674:component/c5751cc6-3513-4070-9deb-af31e86aed34/45ef6a6c-98b8-4615-940d-e9013db36999
3
3
  name: '@atlaskit/editor-plugin-autocomplete'
4
- ownerId: ari:cloud:identity::team/0250ee69-f755-47fd-a468-bf8a9d10a3c5 # Editor AI
4
+ ownerId: ari:cloud:identity::team/cf6a670b-5252-4c68-a769-9207de366beb # Editor Developers
5
5
  labels:
6
6
  - platform-code
7
7
  - platform-afm
@@ -23,7 +23,7 @@ links:
23
23
  customFields:
24
24
  - name: Department
25
25
  type: text
26
- value: Eng - Editor AI
26
+ value: Editor Developers
27
27
  - name: Trusted Reviewer Teams
28
28
  type: text
29
29
  value: ari:cloud:identity::team/cf6a670b-5252-4c68-a769-9207de366beb
@@ -39,6 +39,7 @@ var EXPERIENCE_NAME = exports.EXPERIENCE_NAME = {
39
39
  SLOW_LANE_FETCH: 'slow-lane-fetch',
40
40
  LOAD_VOCABULARY: 'load-vocabulary',
41
41
  LOAD_VECTORS: 'load-vectors',
42
+ LOAD_PHRASES: 'load-phrases',
42
43
  LOAD_GRAMMAR: 'load-grammar'
43
44
  };
44
45
  var isUfoEnabled = function isUfoEnabled() {
@@ -57,7 +58,7 @@ var operationConfig = {
57
58
  })
58
59
  }
59
60
  };
60
- var experiences = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, EXPERIENCE_NAME.SLOW_LANE_FETCH, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.SLOW_LANE_FETCH, operationConfig)), EXPERIENCE_NAME.LOAD_VOCABULARY, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_VOCABULARY, operationConfig)), EXPERIENCE_NAME.LOAD_VECTORS, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_VECTORS, operationConfig)), EXPERIENCE_NAME.LOAD_GRAMMAR, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_GRAMMAR, operationConfig));
61
+ var experiences = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, EXPERIENCE_NAME.SLOW_LANE_FETCH, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.SLOW_LANE_FETCH, operationConfig)), EXPERIENCE_NAME.LOAD_VOCABULARY, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_VOCABULARY, operationConfig)), EXPERIENCE_NAME.LOAD_VECTORS, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_VECTORS, operationConfig)), EXPERIENCE_NAME.LOAD_PHRASES, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_PHRASES, operationConfig)), EXPERIENCE_NAME.LOAD_GRAMMAR, new _ufo.ConcurrentExperience(EXPERIENCE_NAME.LOAD_GRAMMAR, operationConfig));
61
62
  var startExp = exports.startExp = function startExp(name, id, metadata) {
62
63
  if (!isUfoEnabled()) {
63
64
  return;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.fetchAutocompleteArtifactJson = exports.fetchAutocompleteArtifactBinary = exports.buildAutocompleteGatewayUrl = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
10
+ var _artifactsManifest = require("./artifacts-manifest");
11
+ var _debugMode = require("./debug-mode");
12
+ /**
13
+ * Validation and diagnostics layer over the artifacts manifest.
14
+ *
15
+ * `artifacts-manifest` owns *where* a payload comes from (one manifest request,
16
+ * then a presigned CDN download). This module owns *whether the payload is
17
+ * usable*: every loader declares the shape it expects, so a mis-published
18
+ * artifact fails at the boundary with the artifact's name rather than surfacing
19
+ * later as an empty trie or a silent no-op in scoring.
20
+ */
21
+
22
+ var TRAILING_SLASH_REGEX = /\/$/;
23
+ var DEFAULT_BASE_URL = '';
24
+ var AUTOCOMPLETE_GATEWAY_BASE = '/gateway/api/v1/autocomplete';
25
+ /**
26
+ * Build a URL for one of the autocomplete gateway's own endpoints (e.g. the
27
+ * network slow lane). Model artifacts do NOT go through here — they are served
28
+ * from the CDN via the manifest.
29
+ */
30
+ var buildAutocompleteGatewayUrl = exports.buildAutocompleteGatewayUrl = function buildAutocompleteGatewayUrl(path) {
31
+ var baseUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_BASE_URL;
32
+ var normalizedBase = baseUrl.replace(TRAILING_SLASH_REGEX, '');
33
+ return "".concat(normalizedBase).concat(AUTOCOMPLETE_GATEWAY_BASE).concat(path);
34
+ };
35
+
36
+ /**
37
+ * Download a JSON artifact and assert its shape before handing it to a loader.
38
+ *
39
+ * :params:
40
+ * artifactName: Manifest key for the artifact
41
+ * options.label: Name used in diagnostics; defaults to the manifest key
42
+ * options.summarize: Renders a short size/count summary for the debug log
43
+ * options.validate: Type guard the payload must satisfy
44
+ * :returns:
45
+ * The parsed, validated payload
46
+ */
47
+ var fetchAutocompleteArtifactJson = exports.fetchAutocompleteArtifactJson = /*#__PURE__*/function () {
48
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(artifactName) {
49
+ var _options$label, _options$summarize;
50
+ var options,
51
+ label,
52
+ payload,
53
+ summary,
54
+ _args = arguments;
55
+ return _regenerator.default.wrap(function (_context) {
56
+ while (1) switch (_context.prev = _context.next) {
57
+ case 0:
58
+ options = _args.length > 1 && _args[1] !== undefined ? _args[1] : {};
59
+ label = (_options$label = options.label) !== null && _options$label !== void 0 ? _options$label : artifactName; // Presigned CDN URLs carry an auth token, so only the artifact name is logged.
60
+ (0, _debugMode.ctcTag)('init', "\u2193 loading ".concat(label));
61
+ _context.next = 1;
62
+ return (0, _artifactsManifest.fetchArtifactJson)(artifactName);
63
+ case 1:
64
+ payload = _context.sent;
65
+ if (!(options.validate && !options.validate(payload))) {
66
+ _context.next = 2;
67
+ break;
68
+ }
69
+ throw new Error("[autocomplete-artifacts] ".concat(label, " payload shape was invalid"));
70
+ case 2:
71
+ summary = (_options$summarize = options.summarize) === null || _options$summarize === void 0 ? void 0 : _options$summarize.call(options, payload);
72
+ (0, _debugMode.ctcTag)('init', "\u2713 loaded ".concat(label).concat(summary ? " (".concat(summary, ")") : ''));
73
+ return _context.abrupt("return", payload);
74
+ case 3:
75
+ case "end":
76
+ return _context.stop();
77
+ }
78
+ }, _callee);
79
+ }));
80
+ return function fetchAutocompleteArtifactJson(_x) {
81
+ return _ref.apply(this, arguments);
82
+ };
83
+ }();
84
+
85
+ /**
86
+ * Download a binary artifact (the word-vectors blob) as an ArrayBuffer.
87
+ *
88
+ * :params:
89
+ * artifactName: Manifest key for the artifact
90
+ * label: Name used in diagnostics; defaults to the manifest key
91
+ * :returns:
92
+ * The raw bytes of the artifact
93
+ */
94
+ var fetchAutocompleteArtifactBinary = exports.fetchAutocompleteArtifactBinary = /*#__PURE__*/function () {
95
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(artifactName) {
96
+ var label,
97
+ url,
98
+ response,
99
+ payload,
100
+ _args2 = arguments;
101
+ return _regenerator.default.wrap(function (_context2) {
102
+ while (1) switch (_context2.prev = _context2.next) {
103
+ case 0:
104
+ label = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : artifactName;
105
+ (0, _debugMode.ctcTag)('init', "\u2193 loading ".concat(label));
106
+ _context2.next = 1;
107
+ return (0, _artifactsManifest.getArtifactUrl)(artifactName);
108
+ case 1:
109
+ url = _context2.sent;
110
+ _context2.next = 2;
111
+ return fetch(url);
112
+ case 2:
113
+ response = _context2.sent;
114
+ if (response.ok) {
115
+ _context2.next = 3;
116
+ break;
117
+ }
118
+ throw new Error("[autocomplete-artifacts] Failed to fetch ".concat(label, ": ").concat(response.status));
119
+ case 3:
120
+ _context2.next = 4;
121
+ return response.arrayBuffer();
122
+ case 4:
123
+ payload = _context2.sent;
124
+ (0, _debugMode.ctcTag)('init', "\u2713 loaded ".concat(label, " (").concat(payload.byteLength, " bytes)"));
125
+ return _context2.abrupt("return", payload);
126
+ case 5:
127
+ case "end":
128
+ return _context2.stop();
129
+ }
130
+ }, _callee2);
131
+ }));
132
+ return function fetchAutocompleteArtifactBinary(_x2) {
133
+ return _ref2.apply(this, arguments);
134
+ };
135
+ }();
@@ -28,10 +28,13 @@ var _debugMode = require("./debug-mode");
28
28
  * hyphenated, unlike the underscored filenames the artifacts are generated from.
29
29
  */
30
30
  var ARTIFACT_NAME = exports.ARTIFACT_NAME = {
31
+ BIGRAMS: 'bigrams.json',
31
32
  FIRST_TOKEN_TO_WORDS: 'first-token-to-words.json',
32
33
  GHOST_POS_TAGS: 'ghost-pos-tags.json',
33
34
  GRAMMAR_TRANSITIONS: 'grammar-transitions-10k.json',
34
35
  L3_VOCABULARY: 'l3-vocabulary.json',
36
+ PHRASE_CONTINUATION_TOKENS: 'phrase-continuation-tokens.json',
37
+ PHRASES: 'phrases.json',
35
38
  POS_TAGS: 'combined-l2-l3-pos-tags.json',
36
39
  VOCABULARY: 'vocabulary-10k.json',
37
40
  WORD_INDEX: 'word-index-10k.json',