@atlaskit/editor-plugin-mentions 14.6.3 → 14.6.5

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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-mentions
2
2
 
3
+ ## 14.6.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`d9dedaf4289ad`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d9dedaf4289ad) -
8
+ Migrate deprecated Lozenge appearance values to the new semantic appearances, and migrate
9
+ deprecated `SimpleTag`/`RemovableTag` to the default `Tag` export (SimpleTag with
10
+ `isRemovable={false}`).
11
+
12
+ ## 14.6.4
13
+
14
+ ### Patch Changes
15
+
16
+ - [`8634e07b0f9f5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8634e07b0f9f5) -
17
+ Fix agent name not showing in nudge on copy paste
18
+ - Updated dependencies
19
+
3
20
  ## 14.6.3
4
21
 
5
22
  ### Patch Changes
@@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.mentionsPlugin = void 0;
9
- var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
13
  var _react = _interopRequireWildcard(require("react"));
13
14
  var _reactIntl = require("react-intl");
@@ -27,9 +28,10 @@ var _mentionPlaceholder = require("./pm-plugins/mentionPlaceholder");
27
28
  var _InlineInviteRecaptchaContainer = require("./ui/InlineInviteRecaptchaContainer");
28
29
  var _SecondaryToolbarComponent = require("./ui/SecondaryToolbarComponent");
29
30
  var _typeAhead = require("./ui/type-ahead");
31
+ var _excluded2 = ["pendingPastedAgentMention"]; // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
30
32
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
31
33
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
32
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
34
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
33
35
  var processName = function processName(name, intl) {
34
36
  var unknownLabel = intl.formatMessage(_messages.mentionMessages.unknownLabel);
35
37
  if (name.status === _types.MentionNameStatus.OK) {
@@ -253,13 +255,19 @@ var mentionsPlugin = exports.mentionsPlugin = function mentionsPlugin(_ref3) {
253
255
  return undefined;
254
256
  }
255
257
  var mentionPluginState = _key.mentionPluginKey.getState(editorState);
256
- return _objectSpread(_objectSpread({}, mentionPluginState), {}, {
258
+ // Exclude pendingPastedAgentMention it is an @internal transient field and
259
+ // should not be part of the public shared state API. Exposing it would cause
260
+ // unnecessary re-renders in subscribers and leak implementation details.
261
+ var _ref8 = mentionPluginState !== null && mentionPluginState !== void 0 ? mentionPluginState : {},
262
+ _excluded = _ref8.pendingPastedAgentMention,
263
+ publicPluginState = (0, _objectWithoutProperties2.default)(_ref8, _excluded2);
264
+ return _objectSpread(_objectSpread({}, publicPluginState), {}, {
257
265
  typeAheadHandler: typeAhead
258
266
  });
259
267
  },
260
268
  pluginsOptions: {
261
- quickInsert: function quickInsert(_ref8) {
262
- var formatMessage = _ref8.formatMessage;
269
+ quickInsert: function quickInsert(_ref9) {
270
+ var formatMessage = _ref9.formatMessage;
263
271
  return [{
264
272
  id: 'mention',
265
273
  title: formatMessage(_messages.toolbarInsertBlockMessages.mention),
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.ACTIONS = void 0;
8
8
  exports.createMentionPlugin = createMentionPlugin;
9
+ exports.resolveAndDispatchPastedAgentMentionName = void 0;
9
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
11
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
12
  var _analytics = require("@atlaskit/editor-common/analytics");
@@ -29,7 +30,19 @@ var ACTIONS = exports.ACTIONS = {
29
30
  COMMIT_PENDING_TYPED_AGENT_MENTION: 'COMMIT_PENDING_TYPED_AGENT_MENTION',
30
31
  DISCARD_PENDING_TYPED_AGENT_MENTION: 'DISCARD_PENDING_TYPED_AGENT_MENTION',
31
32
  SET_PENDING_TYPED_AGENT_MENTION: 'SET_PENDING_TYPED_AGENT_MENTION',
32
- SET_PROVIDER: 'SET_PROVIDER'
33
+ SET_PROVIDER: 'SET_PROVIDER',
34
+ /**
35
+ * Dispatched from view().update() when async resolveMentionName() resolves
36
+ * for a pasted agent mention.
37
+ * Updates lastInsertedAgentMentionName so the nudge shows the correct name.
38
+ */
39
+ RESOLVE_PASTED_AGENT_MENTION_NAME: 'RESOLVE_PASTED_AGENT_MENTION_NAME',
40
+ /**
41
+ * Dispatched from view().update() when async resolveMentionName() resolves
42
+ * with a non-OK status for a pasted agent mention.
43
+ * Clears pendingPastedAgentMention so no retry loop occurs.
44
+ */
45
+ CLEAR_PENDING_PASTED_AGENT_MENTION: 'CLEAR_PENDING_PASTED_AGENT_MENTION'
33
46
  };
34
47
 
35
48
  // 'AGENT' is not in the ADF schema UserType enum but is used at runtime.
@@ -53,7 +66,7 @@ var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
53
66
  var AGENT_MENTION_INACTIVITY_MS = 3000;
54
67
  var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
55
68
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
56
- var PACKAGE_VERSION = "14.6.2";
69
+ var PACKAGE_VERSION = "14.6.4";
57
70
  var setProvider = function setProvider(provider) {
58
71
  return function (state, dispatch) {
59
72
  if (dispatch) {
@@ -229,7 +242,7 @@ var commitPendingTypedAgentMention = function commitPendingTypedAgentMention(sta
229
242
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
230
243
  };
231
244
  var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginState) {
232
- return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
245
+ return Boolean(pluginState.pendingTypedAgentMention) || Boolean(pluginState.pendingPastedAgentMention) && (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes') || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
233
246
  };
234
247
 
235
248
  /**
@@ -238,8 +251,11 @@ var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginSta
238
251
  * lastInserted* details from the previous document must be cleared together.
239
252
  */
240
253
  var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(pluginState) {
241
- return _objectSpread(_objectSpread({}, pluginState), {}, {
242
- pendingTypedAgentMention: null,
254
+ return _objectSpread(_objectSpread(_objectSpread({}, pluginState), {}, {
255
+ pendingTypedAgentMention: null
256
+ }, (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes') ? {
257
+ pendingPastedAgentMention: null
258
+ } : {}), {}, {
243
259
  lastInsertedAgentMentionId: null,
244
260
  lastInsertedAgentMentionLocalId: null,
245
261
  lastInsertedAgentMentionContext: null,
@@ -248,6 +264,88 @@ var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(plugi
248
264
  lastInsertedAgentMentionParentNodeType: null
249
265
  });
250
266
  };
267
+
268
+ /**
269
+ * Attempts to synchronously resolve an agent mention name from the mention
270
+ * provider's cache. Falls back to undefined if the provider doesn't support
271
+ * name resolution, the result is a Promise (async/cache miss), or the status
272
+ * is not OK.
273
+ */
274
+ var resolveCachedAgentMentionName = function resolveCachedAgentMentionName(mentionProvider, params, id) {
275
+ if (params !== null && params !== void 0 && params.name || !(0, _resource.isResolvingMentionProvider)(mentionProvider)) {
276
+ var _params$name;
277
+ return (_params$name = params === null || params === void 0 ? void 0 : params.name) !== null && _params$name !== void 0 ? _params$name : undefined;
278
+ }
279
+ var result = mentionProvider.resolveMentionName(id);
280
+ if (!(result instanceof Promise) && result.status === _resource.MentionNameStatus.OK) {
281
+ return result.name || undefined;
282
+ }
283
+ return undefined;
284
+ };
285
+
286
+ /**
287
+ * Resolves the name of a pasted agent mention via the mention provider and
288
+ * dispatches the appropriate action to update plugin state.
289
+ *
290
+ * Handles both async (Promise) and synchronous cache-hit results:
291
+ * - On OK resolution → dispatches RESOLVE_PASTED_AGENT_MENTION_NAME so the nudge
292
+ * shows the correct agent name.
293
+ * - On non-OK result → dispatches CLEAR_PENDING_PASTED_AGENT_MENTION to prevent
294
+ * an infinite retry loop on subsequent update() calls.
295
+ *
296
+ * Guards against duplicate in-flight requests via pendingResolveMentionIds.
297
+ */
298
+ var resolveAndDispatchPastedAgentMentionName = exports.resolveAndDispatchPastedAgentMentionName = function resolveAndDispatchPastedAgentMentionName(agentId, mentionProvider, pendingResolveMentionIds, view) {
299
+ if (pendingResolveMentionIds.has(agentId)) {
300
+ return;
301
+ }
302
+ pendingResolveMentionIds.add(agentId);
303
+ var result = mentionProvider.resolveMentionName(agentId);
304
+ if (result instanceof Promise) {
305
+ result.then(function (nameDetails) {
306
+ pendingResolveMentionIds.delete(agentId);
307
+ if (nameDetails.status === _resource.MentionNameStatus.OK && nameDetails.name) {
308
+ view.dispatch(view.state.tr.setMeta(_key.mentionPluginKey, {
309
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
310
+ params: {
311
+ id: agentId,
312
+ name: nameDetails.name
313
+ }
314
+ }));
315
+ } else {
316
+ // Non-OK status — clear pendingPastedAgentMention to prevent
317
+ // an infinite retry loop on subsequent update() calls.
318
+ view.dispatch(view.state.tr.setMeta(_key.mentionPluginKey, {
319
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
320
+ params: {
321
+ id: agentId
322
+ }
323
+ }));
324
+ }
325
+ });
326
+ } else if (result.status === _resource.MentionNameStatus.OK && result.name) {
327
+ pendingResolveMentionIds.delete(agentId);
328
+ // Synchronous hit on a second update cycle (e.g. provider warmed up
329
+ // between the paste transaction and this view update).
330
+ view.dispatch(view.state.tr.setMeta(_key.mentionPluginKey, {
331
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
332
+ params: {
333
+ id: agentId,
334
+ name: result.name
335
+ }
336
+ }));
337
+ } else {
338
+ pendingResolveMentionIds.delete(agentId);
339
+ // Non-OK synchronous status — clear pendingPastedAgentMention to prevent
340
+ // an infinite retry loop on subsequent update() calls.
341
+ view.dispatch(view.state.tr.setMeta(_key.mentionPluginKey, {
342
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
343
+ params: {
344
+ id: agentId
345
+ }
346
+ }));
347
+ }
348
+ };
251
349
  function createMentionPlugin(_ref2) {
252
350
  var pmPluginFactoryParams = _ref2.pmPluginFactoryParams,
253
351
  fireEvent = _ref2.fireEvent,
@@ -331,6 +429,37 @@ function createMentionPlugin(_ref2) {
331
429
  });
332
430
  hasPublicPluginStateChanged = true;
333
431
  break;
432
+ case ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME:
433
+ {
434
+ var _newPluginState$pendi, _newPluginState$pendi2, _newPluginState$pendi3, _newPluginState$pendi4, _newPluginState$pendi5, _newPluginState$pendi6;
435
+ // Guard: only apply if there is a matching pending pasted mention (staleness check).
436
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || !(params !== null && params !== void 0 && params.name) || ((_newPluginState$pendi = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi === void 0 ? void 0 : _newPluginState$pendi.id) !== params.id || !(0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes')) {
437
+ break;
438
+ }
439
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
440
+ pendingPastedAgentMention: null,
441
+ lastInsertedAgentMentionId: (_newPluginState$pendi2 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi2 === void 0 ? void 0 : _newPluginState$pendi2.id,
442
+ lastInsertedAgentMentionLocalId: (_newPluginState$pendi3 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi3 === void 0 ? void 0 : _newPluginState$pendi3.localId,
443
+ lastInsertedAgentMentionContext: (_newPluginState$pendi4 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi4 === void 0 ? void 0 : _newPluginState$pendi4.context,
444
+ lastInsertedAgentMentionName: params.name,
445
+ lastInsertedAgentMentionPrompt: (_newPluginState$pendi5 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi5 === void 0 ? void 0 : _newPluginState$pendi5.prompt,
446
+ lastInsertedAgentMentionParentNodeType: (_newPluginState$pendi6 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi6 === void 0 ? void 0 : _newPluginState$pendi6.parentNodeType
447
+ });
448
+ hasPublicPluginStateChanged = true;
449
+ break;
450
+ }
451
+ case ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION:
452
+ {
453
+ var _newPluginState$pendi7;
454
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || ((_newPluginState$pendi7 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi7 === void 0 ? void 0 : _newPluginState$pendi7.id) !== params.id || !(0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes')) {
455
+ break;
456
+ }
457
+ // resolveMentionName() returned a non-OK status — clear the pending state.
458
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
459
+ pendingPastedAgentMention: null
460
+ });
461
+ break;
462
+ }
334
463
  }
335
464
 
336
465
  // When the agent mentions experiment is off, dispatch immediately (original behaviour).
@@ -475,9 +604,12 @@ function createMentionPlugin(_ref2) {
475
604
  }, params.name);
476
605
  }
477
606
  if (agentMentionLocalId === null && node.attrs.localId) {
607
+ // Try to recover the name synchronously from the mention provider's
608
+ // name cache (populated by cacheMentionName on typed insert).
609
+ var cachedName = (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes') ? resolveCachedAgentMentionName(mentionProvider, params, node.attrs.id) : params === null || params === void 0 ? void 0 : params.name;
478
610
  var agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
479
611
  return attrs.localId === node.attrs.localId;
480
- }, params === null || params === void 0 ? void 0 : params.name);
612
+ }, cachedName);
481
613
  if (agentMentionDetails) {
482
614
  agentMentionId = agentMentionDetails.id;
483
615
  agentMentionLocalId = agentMentionDetails.localId;
@@ -595,6 +727,20 @@ function createMentionPlugin(_ref2) {
595
727
  if (!isTaskItemMentionForPaste && isNewInsertion && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
596
728
  // Rovo is already open — skip setting lastInsertedAgentMention* so the
597
729
  // downstream nudge listener never fires.
730
+ } else if (agentMentionName === null && agentMentionId !== null && (0, _resource.isResolvingMentionProvider)(newPluginState.mentionProvider) && (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes')) {
731
+ // Store details in pendingPastedAgentMention (private, not broadcast), preventing a double-nudge.
732
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
733
+ pendingPastedAgentMention: {
734
+ id: agentMentionId,
735
+ localId: agentMentionLocalId,
736
+ context: agentMentionContext,
737
+ prompt: agentMentionPrompt,
738
+ parentNodeType: agentMentionParentNodeType
739
+ }
740
+ }, newInsertionCount !== undefined ? {
741
+ lastAgentMentionInsertionCount: newInsertionCount
742
+ } : {});
743
+ // the nudge does not fire until the name is resolved.
598
744
  } else {
599
745
  // Not suppressed — update state so the nudge fires normally.
600
746
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
@@ -678,6 +824,9 @@ function createMentionPlugin(_ref2) {
678
824
  var pendingTypedAgentMentionTimer;
679
825
  var pendingTypedAgentMentionTimerKey = null;
680
826
  var pendingTypedAgentMentionFocusDeferCount = 0;
827
+ // Tracks agent IDs for which resolveMentionName() is already in-flight,
828
+ // preventing duplicate concurrent Promises for the same ID across update() cycles.
829
+ var pendingResolveMentionIds = new Set();
681
830
 
682
831
  /**
683
832
  * Clears the currently scheduled pending typed-agent-mention timer.
@@ -822,11 +971,19 @@ function createMentionPlugin(_ref2) {
822
971
  }
823
972
  return {
824
973
  update: function update(view, prevState) {
974
+ var _mentionPluginState$p;
825
975
  var mentionPluginState = _key.mentionPluginKey.getState(view.state);
826
976
  if (mentionPluginState === _key.mentionPluginKey.getState(prevState)) {
827
977
  return;
828
978
  }
829
979
  _schedulePendingTypedAgentMentionTimer(mentionPluginState);
980
+
981
+ // If a pasted agent mention has no name (cache miss), resolve it async
982
+ // via the mention provider and dispatch RESOLVE_PASTED_AGENT_MENTION_NAME
983
+ // so the nudge displays the correct name.
984
+ if ((0, _experiments.editorExperiment)('platform_editor_agent_mentions', true) && (mentionPluginState === null || mentionPluginState === void 0 || (_mentionPluginState$p = mentionPluginState.pendingPastedAgentMention) === null || _mentionPluginState$p === void 0 ? void 0 : _mentionPluginState$p.id) != null && mentionPluginState !== null && mentionPluginState !== void 0 && mentionPluginState.mentionProvider && (0, _resource.isResolvingMentionProvider)(mentionPluginState.mentionProvider) && (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes')) {
985
+ resolveAndDispatchPastedAgentMentionName(mentionPluginState.pendingPastedAgentMention.id, mentionPluginState.mentionProvider, pendingResolveMentionIds, view);
986
+ }
830
987
  },
831
988
  destroy: function destroy() {
832
989
  clearPendingTypedAgentMentionTimer();
@@ -410,7 +410,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
410
410
  showWhenOnlySection: true
411
411
  },
412
412
  lozenge: /*#__PURE__*/_react.default.createElement(_lozenge.default, {
413
- appearance: "new"
413
+ appearance: "discovery"
414
414
  }, intl.formatMessage(_messages.mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
415
415
  }];
416
416
  },
@@ -545,6 +545,11 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
545
545
  name: name
546
546
  }
547
547
  });
548
+ // Cache the agent name so pasted mentions (where attrs.text is stripped)
549
+ // can recover it synchronously via resolveMentionName() cache hit.
550
+ if (name && mentionProvider && (0, _resource.isResolvingMentionProvider)(mentionProvider) && (0, _platformFeatureFlags.fg)('platform_editor_agent_mentions_drop_one_fixes')) {
551
+ mentionProvider.cacheMentionName(id, name);
552
+ }
548
553
  }
549
554
  return tr;
550
555
  },
@@ -226,8 +226,15 @@ const mentionsPlugin = ({
226
226
  return undefined;
227
227
  }
228
228
  const mentionPluginState = mentionPluginKey.getState(editorState);
229
+ // Exclude pendingPastedAgentMention — it is an @internal transient field and
230
+ // should not be part of the public shared state API. Exposing it would cause
231
+ // unnecessary re-renders in subscribers and leak implementation details.
232
+ const {
233
+ pendingPastedAgentMention: _excluded,
234
+ ...publicPluginState
235
+ } = mentionPluginState !== null && mentionPluginState !== void 0 ? mentionPluginState : {};
229
236
  return {
230
- ...mentionPluginState,
237
+ ...publicPluginState,
231
238
  typeAheadHandler: typeAhead
232
239
  };
233
240
  },
@@ -1,7 +1,7 @@
1
1
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
3
  import { insm } from '@atlaskit/insm';
4
- import { SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
4
+ import { isResolvingMentionProvider, MentionNameStatus, SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
5
5
  import { ComponentNames } from '@atlaskit/mention/types';
6
6
  import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -14,7 +14,19 @@ export const ACTIONS = {
14
14
  COMMIT_PENDING_TYPED_AGENT_MENTION: 'COMMIT_PENDING_TYPED_AGENT_MENTION',
15
15
  DISCARD_PENDING_TYPED_AGENT_MENTION: 'DISCARD_PENDING_TYPED_AGENT_MENTION',
16
16
  SET_PENDING_TYPED_AGENT_MENTION: 'SET_PENDING_TYPED_AGENT_MENTION',
17
- SET_PROVIDER: 'SET_PROVIDER'
17
+ SET_PROVIDER: 'SET_PROVIDER',
18
+ /**
19
+ * Dispatched from view().update() when async resolveMentionName() resolves
20
+ * for a pasted agent mention.
21
+ * Updates lastInsertedAgentMentionName so the nudge shows the correct name.
22
+ */
23
+ RESOLVE_PASTED_AGENT_MENTION_NAME: 'RESOLVE_PASTED_AGENT_MENTION_NAME',
24
+ /**
25
+ * Dispatched from view().update() when async resolveMentionName() resolves
26
+ * with a non-OK status for a pasted agent mention.
27
+ * Clears pendingPastedAgentMention so no retry loop occurs.
28
+ */
29
+ CLEAR_PENDING_PASTED_AGENT_MENTION: 'CLEAR_PENDING_PASTED_AGENT_MENTION'
18
30
  };
19
31
 
20
32
  // 'AGENT' is not in the ADF schema UserType enum but is used at runtime.
@@ -38,7 +50,7 @@ const AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
38
50
  const AGENT_MENTION_INACTIVITY_MS = 3000;
39
51
  const MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
40
52
  const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
41
- const PACKAGE_VERSION = "14.6.2";
53
+ const PACKAGE_VERSION = "14.6.4";
42
54
  const setProvider = provider => (state, dispatch) => {
43
55
  if (dispatch) {
44
56
  dispatch(state.tr.setMeta(mentionPluginKey, {
@@ -206,7 +218,7 @@ const commitPendingTypedAgentMention = (state, pluginState, pendingTypedAgentMen
206
218
  }
207
219
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
208
220
  };
209
- const hasTrackedAgentMentionState = pluginState => Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
221
+ const hasTrackedAgentMentionState = pluginState => Boolean(pluginState.pendingTypedAgentMention) || Boolean(pluginState.pendingPastedAgentMention) && fg('platform_editor_agent_mentions_drop_one_fixes') || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
210
222
 
211
223
  /**
212
224
  * Clears agent mention state that points at a specific document snapshot.
@@ -217,6 +229,9 @@ const clearTrackedAgentMentionState = pluginState => {
217
229
  return {
218
230
  ...pluginState,
219
231
  pendingTypedAgentMention: null,
232
+ ...(fg('platform_editor_agent_mentions_drop_one_fixes') ? {
233
+ pendingPastedAgentMention: null
234
+ } : {}),
220
235
  lastInsertedAgentMentionId: null,
221
236
  lastInsertedAgentMentionLocalId: null,
222
237
  lastInsertedAgentMentionContext: null,
@@ -225,6 +240,88 @@ const clearTrackedAgentMentionState = pluginState => {
225
240
  lastInsertedAgentMentionParentNodeType: null
226
241
  };
227
242
  };
243
+
244
+ /**
245
+ * Attempts to synchronously resolve an agent mention name from the mention
246
+ * provider's cache. Falls back to undefined if the provider doesn't support
247
+ * name resolution, the result is a Promise (async/cache miss), or the status
248
+ * is not OK.
249
+ */
250
+ const resolveCachedAgentMentionName = (mentionProvider, params, id) => {
251
+ if (params !== null && params !== void 0 && params.name || !isResolvingMentionProvider(mentionProvider)) {
252
+ var _params$name;
253
+ return (_params$name = params === null || params === void 0 ? void 0 : params.name) !== null && _params$name !== void 0 ? _params$name : undefined;
254
+ }
255
+ const result = mentionProvider.resolveMentionName(id);
256
+ if (!(result instanceof Promise) && result.status === MentionNameStatus.OK) {
257
+ return result.name || undefined;
258
+ }
259
+ return undefined;
260
+ };
261
+
262
+ /**
263
+ * Resolves the name of a pasted agent mention via the mention provider and
264
+ * dispatches the appropriate action to update plugin state.
265
+ *
266
+ * Handles both async (Promise) and synchronous cache-hit results:
267
+ * - On OK resolution → dispatches RESOLVE_PASTED_AGENT_MENTION_NAME so the nudge
268
+ * shows the correct agent name.
269
+ * - On non-OK result → dispatches CLEAR_PENDING_PASTED_AGENT_MENTION to prevent
270
+ * an infinite retry loop on subsequent update() calls.
271
+ *
272
+ * Guards against duplicate in-flight requests via pendingResolveMentionIds.
273
+ */
274
+ export const resolveAndDispatchPastedAgentMentionName = (agentId, mentionProvider, pendingResolveMentionIds, view) => {
275
+ if (pendingResolveMentionIds.has(agentId)) {
276
+ return;
277
+ }
278
+ pendingResolveMentionIds.add(agentId);
279
+ const result = mentionProvider.resolveMentionName(agentId);
280
+ if (result instanceof Promise) {
281
+ result.then(nameDetails => {
282
+ pendingResolveMentionIds.delete(agentId);
283
+ if (nameDetails.status === MentionNameStatus.OK && nameDetails.name) {
284
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
285
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
286
+ params: {
287
+ id: agentId,
288
+ name: nameDetails.name
289
+ }
290
+ }));
291
+ } else {
292
+ // Non-OK status — clear pendingPastedAgentMention to prevent
293
+ // an infinite retry loop on subsequent update() calls.
294
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
295
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
296
+ params: {
297
+ id: agentId
298
+ }
299
+ }));
300
+ }
301
+ });
302
+ } else if (result.status === MentionNameStatus.OK && result.name) {
303
+ pendingResolveMentionIds.delete(agentId);
304
+ // Synchronous hit on a second update cycle (e.g. provider warmed up
305
+ // between the paste transaction and this view update).
306
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
307
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
308
+ params: {
309
+ id: agentId,
310
+ name: result.name
311
+ }
312
+ }));
313
+ } else {
314
+ pendingResolveMentionIds.delete(agentId);
315
+ // Non-OK synchronous status — clear pendingPastedAgentMention to prevent
316
+ // an infinite retry loop on subsequent update() calls.
317
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
318
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
319
+ params: {
320
+ id: agentId
321
+ }
322
+ }));
323
+ }
324
+ };
228
325
  export function createMentionPlugin({
229
326
  pmPluginFactoryParams,
230
327
  fireEvent,
@@ -314,6 +411,39 @@ export function createMentionPlugin({
314
411
  };
315
412
  hasPublicPluginStateChanged = true;
316
413
  break;
414
+ case ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME:
415
+ {
416
+ var _newPluginState$pendi, _newPluginState$pendi2, _newPluginState$pendi3, _newPluginState$pendi4, _newPluginState$pendi5, _newPluginState$pendi6;
417
+ // Guard: only apply if there is a matching pending pasted mention (staleness check).
418
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || !(params !== null && params !== void 0 && params.name) || ((_newPluginState$pendi = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi === void 0 ? void 0 : _newPluginState$pendi.id) !== params.id || !fg('platform_editor_agent_mentions_drop_one_fixes')) {
419
+ break;
420
+ }
421
+ newPluginState = {
422
+ ...newPluginState,
423
+ pendingPastedAgentMention: null,
424
+ lastInsertedAgentMentionId: (_newPluginState$pendi2 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi2 === void 0 ? void 0 : _newPluginState$pendi2.id,
425
+ lastInsertedAgentMentionLocalId: (_newPluginState$pendi3 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi3 === void 0 ? void 0 : _newPluginState$pendi3.localId,
426
+ lastInsertedAgentMentionContext: (_newPluginState$pendi4 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi4 === void 0 ? void 0 : _newPluginState$pendi4.context,
427
+ lastInsertedAgentMentionName: params.name,
428
+ lastInsertedAgentMentionPrompt: (_newPluginState$pendi5 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi5 === void 0 ? void 0 : _newPluginState$pendi5.prompt,
429
+ lastInsertedAgentMentionParentNodeType: (_newPluginState$pendi6 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi6 === void 0 ? void 0 : _newPluginState$pendi6.parentNodeType
430
+ };
431
+ hasPublicPluginStateChanged = true;
432
+ break;
433
+ }
434
+ case ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION:
435
+ {
436
+ var _newPluginState$pendi7;
437
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || ((_newPluginState$pendi7 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi7 === void 0 ? void 0 : _newPluginState$pendi7.id) !== params.id || !fg('platform_editor_agent_mentions_drop_one_fixes')) {
438
+ break;
439
+ }
440
+ // resolveMentionName() returned a non-OK status — clear the pending state.
441
+ newPluginState = {
442
+ ...newPluginState,
443
+ pendingPastedAgentMention: null
444
+ };
445
+ break;
446
+ }
317
447
  }
318
448
 
319
449
  // When the agent mentions experiment is off, dispatch immediately (original behaviour).
@@ -448,7 +578,10 @@ export function createMentionPlugin({
448
578
  pendingTypedAgentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, attrs => attrs.localId === params.localId, params.name);
449
579
  }
450
580
  if (agentMentionLocalId === null && node.attrs.localId) {
451
- const agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, attrs => attrs.localId === node.attrs.localId, params === null || params === void 0 ? void 0 : params.name);
581
+ // Try to recover the name synchronously from the mention provider's
582
+ // name cache (populated by cacheMentionName on typed insert).
583
+ const cachedName = fg('platform_editor_agent_mentions_drop_one_fixes') ? resolveCachedAgentMentionName(mentionProvider, params, node.attrs.id) : params === null || params === void 0 ? void 0 : params.name;
584
+ const agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, attrs => attrs.localId === node.attrs.localId, cachedName);
452
585
  if (agentMentionDetails) {
453
586
  agentMentionId = agentMentionDetails.id;
454
587
  agentMentionLocalId = agentMentionDetails.localId;
@@ -553,6 +686,22 @@ export function createMentionPlugin({
553
686
  if (!isTaskItemMentionForPaste && isNewInsertion && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
554
687
  // Rovo is already open — skip setting lastInsertedAgentMention* so the
555
688
  // downstream nudge listener never fires.
689
+ } else if (agentMentionName === null && agentMentionId !== null && isResolvingMentionProvider(newPluginState.mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
690
+ // Store details in pendingPastedAgentMention (private, not broadcast), preventing a double-nudge.
691
+ newPluginState = {
692
+ ...newPluginState,
693
+ pendingPastedAgentMention: {
694
+ id: agentMentionId,
695
+ localId: agentMentionLocalId,
696
+ context: agentMentionContext,
697
+ prompt: agentMentionPrompt,
698
+ parentNodeType: agentMentionParentNodeType
699
+ },
700
+ ...(newInsertionCount !== undefined ? {
701
+ lastAgentMentionInsertionCount: newInsertionCount
702
+ } : {})
703
+ };
704
+ // the nudge does not fire until the name is resolved.
556
705
  } else {
557
706
  // Not suppressed — update state so the nudge fires normally.
558
707
  newPluginState = {
@@ -639,6 +788,9 @@ export function createMentionPlugin({
639
788
  let pendingTypedAgentMentionTimer;
640
789
  let pendingTypedAgentMentionTimerKey = null;
641
790
  let pendingTypedAgentMentionFocusDeferCount = 0;
791
+ // Tracks agent IDs for which resolveMentionName() is already in-flight,
792
+ // preventing duplicate concurrent Promises for the same ID across update() cycles.
793
+ const pendingResolveMentionIds = new Set();
642
794
 
643
795
  /**
644
796
  * Clears the currently scheduled pending typed-agent-mention timer.
@@ -779,11 +931,19 @@ export function createMentionPlugin({
779
931
  }
780
932
  return {
781
933
  update(view, prevState) {
934
+ var _mentionPluginState$p;
782
935
  const mentionPluginState = mentionPluginKey.getState(view.state);
783
936
  if (mentionPluginState === mentionPluginKey.getState(prevState)) {
784
937
  return;
785
938
  }
786
939
  schedulePendingTypedAgentMentionTimer(mentionPluginState);
940
+
941
+ // If a pasted agent mention has no name (cache miss), resolve it async
942
+ // via the mention provider and dispatch RESOLVE_PASTED_AGENT_MENTION_NAME
943
+ // so the nudge displays the correct name.
944
+ if (editorExperiment('platform_editor_agent_mentions', true) && (mentionPluginState === null || mentionPluginState === void 0 ? void 0 : (_mentionPluginState$p = mentionPluginState.pendingPastedAgentMention) === null || _mentionPluginState$p === void 0 ? void 0 : _mentionPluginState$p.id) != null && mentionPluginState !== null && mentionPluginState !== void 0 && mentionPluginState.mentionProvider && isResolvingMentionProvider(mentionPluginState.mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
945
+ resolveAndDispatchPastedAgentMentionName(mentionPluginState.pendingPastedAgentMention.id, mentionPluginState.mentionProvider, pendingResolveMentionIds, view);
946
+ }
787
947
  },
788
948
  destroy() {
789
949
  clearPendingTypedAgentMentionTimer();
@@ -377,7 +377,7 @@ export const createTypeAheadConfig = ({
377
377
  showWhenOnlySection: true
378
378
  },
379
379
  lozenge: /*#__PURE__*/React.createElement(Lozenge, {
380
- appearance: "new"
380
+ appearance: "discovery"
381
381
  }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
382
382
  }];
383
383
  },
@@ -522,6 +522,11 @@ export const createTypeAheadConfig = ({
522
522
  name
523
523
  }
524
524
  });
525
+ // Cache the agent name so pasted mentions (where attrs.text is stripped)
526
+ // can recover it synchronously via resolveMentionName() cache hit.
527
+ if (name && mentionProvider && isResolvingMentionProvider(mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
528
+ mentionProvider.cacheMentionName(id, name);
529
+ }
525
530
  }
526
531
  return tr;
527
532
  },
@@ -1,5 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
2
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
+ var _excluded2 = ["pendingPastedAgentMention"];
3
5
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
6
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
@@ -245,13 +247,19 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
245
247
  return undefined;
246
248
  }
247
249
  var mentionPluginState = mentionPluginKey.getState(editorState);
248
- return _objectSpread(_objectSpread({}, mentionPluginState), {}, {
250
+ // Exclude pendingPastedAgentMention it is an @internal transient field and
251
+ // should not be part of the public shared state API. Exposing it would cause
252
+ // unnecessary re-renders in subscribers and leak implementation details.
253
+ var _ref8 = mentionPluginState !== null && mentionPluginState !== void 0 ? mentionPluginState : {},
254
+ _excluded = _ref8.pendingPastedAgentMention,
255
+ publicPluginState = _objectWithoutProperties(_ref8, _excluded2);
256
+ return _objectSpread(_objectSpread({}, publicPluginState), {}, {
249
257
  typeAheadHandler: typeAhead
250
258
  });
251
259
  },
252
260
  pluginsOptions: {
253
- quickInsert: function quickInsert(_ref8) {
254
- var formatMessage = _ref8.formatMessage;
261
+ quickInsert: function quickInsert(_ref9) {
262
+ var formatMessage = _ref9.formatMessage;
255
263
  return [{
256
264
  id: 'mention',
257
265
  title: formatMessage(messages.mention),
@@ -8,7 +8,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
8
8
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
9
9
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
10
10
  import { insm } from '@atlaskit/insm';
11
- import { SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
11
+ import { isResolvingMentionProvider, MentionNameStatus, SLI_EVENT_TYPE, SMART_EVENT_TYPE } from '@atlaskit/mention/resource';
12
12
  import { ComponentNames } from '@atlaskit/mention/types';
13
13
  import { fg } from '@atlaskit/platform-feature-flags';
14
14
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
@@ -21,7 +21,19 @@ export var ACTIONS = {
21
21
  COMMIT_PENDING_TYPED_AGENT_MENTION: 'COMMIT_PENDING_TYPED_AGENT_MENTION',
22
22
  DISCARD_PENDING_TYPED_AGENT_MENTION: 'DISCARD_PENDING_TYPED_AGENT_MENTION',
23
23
  SET_PENDING_TYPED_AGENT_MENTION: 'SET_PENDING_TYPED_AGENT_MENTION',
24
- SET_PROVIDER: 'SET_PROVIDER'
24
+ SET_PROVIDER: 'SET_PROVIDER',
25
+ /**
26
+ * Dispatched from view().update() when async resolveMentionName() resolves
27
+ * for a pasted agent mention.
28
+ * Updates lastInsertedAgentMentionName so the nudge shows the correct name.
29
+ */
30
+ RESOLVE_PASTED_AGENT_MENTION_NAME: 'RESOLVE_PASTED_AGENT_MENTION_NAME',
31
+ /**
32
+ * Dispatched from view().update() when async resolveMentionName() resolves
33
+ * with a non-OK status for a pasted agent mention.
34
+ * Clears pendingPastedAgentMention so no retry loop occurs.
35
+ */
36
+ CLEAR_PENDING_PASTED_AGENT_MENTION: 'CLEAR_PENDING_PASTED_AGENT_MENTION'
25
37
  };
26
38
 
27
39
  // 'AGENT' is not in the ADF schema UserType enum but is used at runtime.
@@ -45,7 +57,7 @@ var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
45
57
  var AGENT_MENTION_INACTIVITY_MS = 3000;
46
58
  var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
47
59
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
48
- var PACKAGE_VERSION = "14.6.2";
60
+ var PACKAGE_VERSION = "14.6.4";
49
61
  var setProvider = function setProvider(provider) {
50
62
  return function (state, dispatch) {
51
63
  if (dispatch) {
@@ -221,7 +233,7 @@ var commitPendingTypedAgentMention = function commitPendingTypedAgentMention(sta
221
233
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
222
234
  };
223
235
  var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginState) {
224
- return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
236
+ return Boolean(pluginState.pendingTypedAgentMention) || Boolean(pluginState.pendingPastedAgentMention) && fg('platform_editor_agent_mentions_drop_one_fixes') || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
225
237
  };
226
238
 
227
239
  /**
@@ -230,8 +242,11 @@ var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginSta
230
242
  * lastInserted* details from the previous document must be cleared together.
231
243
  */
232
244
  var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(pluginState) {
233
- return _objectSpread(_objectSpread({}, pluginState), {}, {
234
- pendingTypedAgentMention: null,
245
+ return _objectSpread(_objectSpread(_objectSpread({}, pluginState), {}, {
246
+ pendingTypedAgentMention: null
247
+ }, fg('platform_editor_agent_mentions_drop_one_fixes') ? {
248
+ pendingPastedAgentMention: null
249
+ } : {}), {}, {
235
250
  lastInsertedAgentMentionId: null,
236
251
  lastInsertedAgentMentionLocalId: null,
237
252
  lastInsertedAgentMentionContext: null,
@@ -240,6 +255,88 @@ var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(plugi
240
255
  lastInsertedAgentMentionParentNodeType: null
241
256
  });
242
257
  };
258
+
259
+ /**
260
+ * Attempts to synchronously resolve an agent mention name from the mention
261
+ * provider's cache. Falls back to undefined if the provider doesn't support
262
+ * name resolution, the result is a Promise (async/cache miss), or the status
263
+ * is not OK.
264
+ */
265
+ var resolveCachedAgentMentionName = function resolveCachedAgentMentionName(mentionProvider, params, id) {
266
+ if (params !== null && params !== void 0 && params.name || !isResolvingMentionProvider(mentionProvider)) {
267
+ var _params$name;
268
+ return (_params$name = params === null || params === void 0 ? void 0 : params.name) !== null && _params$name !== void 0 ? _params$name : undefined;
269
+ }
270
+ var result = mentionProvider.resolveMentionName(id);
271
+ if (!(result instanceof Promise) && result.status === MentionNameStatus.OK) {
272
+ return result.name || undefined;
273
+ }
274
+ return undefined;
275
+ };
276
+
277
+ /**
278
+ * Resolves the name of a pasted agent mention via the mention provider and
279
+ * dispatches the appropriate action to update plugin state.
280
+ *
281
+ * Handles both async (Promise) and synchronous cache-hit results:
282
+ * - On OK resolution → dispatches RESOLVE_PASTED_AGENT_MENTION_NAME so the nudge
283
+ * shows the correct agent name.
284
+ * - On non-OK result → dispatches CLEAR_PENDING_PASTED_AGENT_MENTION to prevent
285
+ * an infinite retry loop on subsequent update() calls.
286
+ *
287
+ * Guards against duplicate in-flight requests via pendingResolveMentionIds.
288
+ */
289
+ export var resolveAndDispatchPastedAgentMentionName = function resolveAndDispatchPastedAgentMentionName(agentId, mentionProvider, pendingResolveMentionIds, view) {
290
+ if (pendingResolveMentionIds.has(agentId)) {
291
+ return;
292
+ }
293
+ pendingResolveMentionIds.add(agentId);
294
+ var result = mentionProvider.resolveMentionName(agentId);
295
+ if (result instanceof Promise) {
296
+ result.then(function (nameDetails) {
297
+ pendingResolveMentionIds.delete(agentId);
298
+ if (nameDetails.status === MentionNameStatus.OK && nameDetails.name) {
299
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
300
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
301
+ params: {
302
+ id: agentId,
303
+ name: nameDetails.name
304
+ }
305
+ }));
306
+ } else {
307
+ // Non-OK status — clear pendingPastedAgentMention to prevent
308
+ // an infinite retry loop on subsequent update() calls.
309
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
310
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
311
+ params: {
312
+ id: agentId
313
+ }
314
+ }));
315
+ }
316
+ });
317
+ } else if (result.status === MentionNameStatus.OK && result.name) {
318
+ pendingResolveMentionIds.delete(agentId);
319
+ // Synchronous hit on a second update cycle (e.g. provider warmed up
320
+ // between the paste transaction and this view update).
321
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
322
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
323
+ params: {
324
+ id: agentId,
325
+ name: result.name
326
+ }
327
+ }));
328
+ } else {
329
+ pendingResolveMentionIds.delete(agentId);
330
+ // Non-OK synchronous status — clear pendingPastedAgentMention to prevent
331
+ // an infinite retry loop on subsequent update() calls.
332
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
333
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
334
+ params: {
335
+ id: agentId
336
+ }
337
+ }));
338
+ }
339
+ };
243
340
  export function createMentionPlugin(_ref2) {
244
341
  var pmPluginFactoryParams = _ref2.pmPluginFactoryParams,
245
342
  fireEvent = _ref2.fireEvent,
@@ -323,6 +420,37 @@ export function createMentionPlugin(_ref2) {
323
420
  });
324
421
  hasPublicPluginStateChanged = true;
325
422
  break;
423
+ case ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME:
424
+ {
425
+ var _newPluginState$pendi, _newPluginState$pendi2, _newPluginState$pendi3, _newPluginState$pendi4, _newPluginState$pendi5, _newPluginState$pendi6;
426
+ // Guard: only apply if there is a matching pending pasted mention (staleness check).
427
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || !(params !== null && params !== void 0 && params.name) || ((_newPluginState$pendi = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi === void 0 ? void 0 : _newPluginState$pendi.id) !== params.id || !fg('platform_editor_agent_mentions_drop_one_fixes')) {
428
+ break;
429
+ }
430
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
431
+ pendingPastedAgentMention: null,
432
+ lastInsertedAgentMentionId: (_newPluginState$pendi2 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi2 === void 0 ? void 0 : _newPluginState$pendi2.id,
433
+ lastInsertedAgentMentionLocalId: (_newPluginState$pendi3 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi3 === void 0 ? void 0 : _newPluginState$pendi3.localId,
434
+ lastInsertedAgentMentionContext: (_newPluginState$pendi4 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi4 === void 0 ? void 0 : _newPluginState$pendi4.context,
435
+ lastInsertedAgentMentionName: params.name,
436
+ lastInsertedAgentMentionPrompt: (_newPluginState$pendi5 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi5 === void 0 ? void 0 : _newPluginState$pendi5.prompt,
437
+ lastInsertedAgentMentionParentNodeType: (_newPluginState$pendi6 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi6 === void 0 ? void 0 : _newPluginState$pendi6.parentNodeType
438
+ });
439
+ hasPublicPluginStateChanged = true;
440
+ break;
441
+ }
442
+ case ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION:
443
+ {
444
+ var _newPluginState$pendi7;
445
+ if (!isAgentMentionsExperimentEnabled || !(params !== null && params !== void 0 && params.id) || ((_newPluginState$pendi7 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi7 === void 0 ? void 0 : _newPluginState$pendi7.id) !== params.id || !fg('platform_editor_agent_mentions_drop_one_fixes')) {
446
+ break;
447
+ }
448
+ // resolveMentionName() returned a non-OK status — clear the pending state.
449
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
450
+ pendingPastedAgentMention: null
451
+ });
452
+ break;
453
+ }
326
454
  }
327
455
 
328
456
  // When the agent mentions experiment is off, dispatch immediately (original behaviour).
@@ -467,9 +595,12 @@ export function createMentionPlugin(_ref2) {
467
595
  }, params.name);
468
596
  }
469
597
  if (agentMentionLocalId === null && node.attrs.localId) {
598
+ // Try to recover the name synchronously from the mention provider's
599
+ // name cache (populated by cacheMentionName on typed insert).
600
+ var cachedName = fg('platform_editor_agent_mentions_drop_one_fixes') ? resolveCachedAgentMentionName(mentionProvider, params, node.attrs.id) : params === null || params === void 0 ? void 0 : params.name;
470
601
  var agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
471
602
  return attrs.localId === node.attrs.localId;
472
- }, params === null || params === void 0 ? void 0 : params.name);
603
+ }, cachedName);
473
604
  if (agentMentionDetails) {
474
605
  agentMentionId = agentMentionDetails.id;
475
606
  agentMentionLocalId = agentMentionDetails.localId;
@@ -587,6 +718,20 @@ export function createMentionPlugin(_ref2) {
587
718
  if (!isTaskItemMentionForPaste && isNewInsertion && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
588
719
  // Rovo is already open — skip setting lastInsertedAgentMention* so the
589
720
  // downstream nudge listener never fires.
721
+ } else if (agentMentionName === null && agentMentionId !== null && isResolvingMentionProvider(newPluginState.mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
722
+ // Store details in pendingPastedAgentMention (private, not broadcast), preventing a double-nudge.
723
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
724
+ pendingPastedAgentMention: {
725
+ id: agentMentionId,
726
+ localId: agentMentionLocalId,
727
+ context: agentMentionContext,
728
+ prompt: agentMentionPrompt,
729
+ parentNodeType: agentMentionParentNodeType
730
+ }
731
+ }, newInsertionCount !== undefined ? {
732
+ lastAgentMentionInsertionCount: newInsertionCount
733
+ } : {});
734
+ // the nudge does not fire until the name is resolved.
590
735
  } else {
591
736
  // Not suppressed — update state so the nudge fires normally.
592
737
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
@@ -670,6 +815,9 @@ export function createMentionPlugin(_ref2) {
670
815
  var pendingTypedAgentMentionTimer;
671
816
  var pendingTypedAgentMentionTimerKey = null;
672
817
  var pendingTypedAgentMentionFocusDeferCount = 0;
818
+ // Tracks agent IDs for which resolveMentionName() is already in-flight,
819
+ // preventing duplicate concurrent Promises for the same ID across update() cycles.
820
+ var pendingResolveMentionIds = new Set();
673
821
 
674
822
  /**
675
823
  * Clears the currently scheduled pending typed-agent-mention timer.
@@ -814,11 +962,19 @@ export function createMentionPlugin(_ref2) {
814
962
  }
815
963
  return {
816
964
  update: function update(view, prevState) {
965
+ var _mentionPluginState$p;
817
966
  var mentionPluginState = mentionPluginKey.getState(view.state);
818
967
  if (mentionPluginState === mentionPluginKey.getState(prevState)) {
819
968
  return;
820
969
  }
821
970
  _schedulePendingTypedAgentMentionTimer(mentionPluginState);
971
+
972
+ // If a pasted agent mention has no name (cache miss), resolve it async
973
+ // via the mention provider and dispatch RESOLVE_PASTED_AGENT_MENTION_NAME
974
+ // so the nudge displays the correct name.
975
+ if (editorExperiment('platform_editor_agent_mentions', true) && (mentionPluginState === null || mentionPluginState === void 0 || (_mentionPluginState$p = mentionPluginState.pendingPastedAgentMention) === null || _mentionPluginState$p === void 0 ? void 0 : _mentionPluginState$p.id) != null && mentionPluginState !== null && mentionPluginState !== void 0 && mentionPluginState.mentionProvider && isResolvingMentionProvider(mentionPluginState.mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
976
+ resolveAndDispatchPastedAgentMentionName(mentionPluginState.pendingPastedAgentMention.id, mentionPluginState.mentionProvider, pendingResolveMentionIds, view);
977
+ }
822
978
  },
823
979
  destroy: function destroy() {
824
980
  clearPendingTypedAgentMentionTimer();
@@ -401,7 +401,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref8) {
401
401
  showWhenOnlySection: true
402
402
  },
403
403
  lozenge: /*#__PURE__*/React.createElement(Lozenge, {
404
- appearance: "new"
404
+ appearance: "discovery"
405
405
  }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
406
406
  }];
407
407
  },
@@ -536,6 +536,11 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref8) {
536
536
  name: name
537
537
  }
538
538
  });
539
+ // Cache the agent name so pasted mentions (where attrs.text is stripped)
540
+ // can recover it synchronously via resolveMentionName() cache hit.
541
+ if (name && mentionProvider && isResolvingMentionProvider(mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
542
+ mentionProvider.cacheMentionName(id, name);
543
+ }
539
544
  }
540
545
  return tr;
541
546
  },
@@ -1,5 +1,7 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import type { ExtractInjectionAPI, PMPluginFactoryParams } from '@atlaskit/editor-common/types';
3
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
4
+ import type { ResolvingMentionProvider } from '@atlaskit/mention/resource';
3
5
  import type { MentionsPlugin } from '../mentionsPluginType';
4
6
  import type { FireElementsChannelEvent, MentionPluginOptions, MentionPluginState } from '../types';
5
7
  export declare const ACTIONS: {
@@ -7,7 +9,32 @@ export declare const ACTIONS: {
7
9
  DISCARD_PENDING_TYPED_AGENT_MENTION: string;
8
10
  SET_PENDING_TYPED_AGENT_MENTION: string;
9
11
  SET_PROVIDER: string;
12
+ /**
13
+ * Dispatched from view().update() when async resolveMentionName() resolves
14
+ * for a pasted agent mention.
15
+ * Updates lastInsertedAgentMentionName so the nudge shows the correct name.
16
+ */
17
+ RESOLVE_PASTED_AGENT_MENTION_NAME: string;
18
+ /**
19
+ * Dispatched from view().update() when async resolveMentionName() resolves
20
+ * with a non-OK status for a pasted agent mention.
21
+ * Clears pendingPastedAgentMention so no retry loop occurs.
22
+ */
23
+ CLEAR_PENDING_PASTED_AGENT_MENTION: string;
10
24
  };
25
+ /**
26
+ * Resolves the name of a pasted agent mention via the mention provider and
27
+ * dispatches the appropriate action to update plugin state.
28
+ *
29
+ * Handles both async (Promise) and synchronous cache-hit results:
30
+ * - On OK resolution → dispatches RESOLVE_PASTED_AGENT_MENTION_NAME so the nudge
31
+ * shows the correct agent name.
32
+ * - On non-OK result → dispatches CLEAR_PENDING_PASTED_AGENT_MENTION to prevent
33
+ * an infinite retry loop on subsequent update() calls.
34
+ *
35
+ * Guards against duplicate in-flight requests via pendingResolveMentionIds.
36
+ */
37
+ export declare const resolveAndDispatchPastedAgentMentionName: (agentId: string, mentionProvider: ResolvingMentionProvider, pendingResolveMentionIds: Set<string>, view: EditorView) => void;
11
38
  interface CreateMentionPlugin {
12
39
  api?: ExtractInjectionAPI<MentionsPlugin>;
13
40
  fireEvent: FireElementsChannelEvent;
@@ -114,6 +114,19 @@ export type MentionPluginState = {
114
114
  lastInsertedAgentMentionPrompt?: string | null;
115
115
  mentionProvider?: MentionProvider;
116
116
  mentions?: Array<MentionDescription>;
117
+ /**
118
+ * @internal Tracks a pasted agent mention pending name resolution (cache miss).
119
+ * view().update() calls resolveMentionName() silently until resolved, then
120
+ * RESOLVE_PASTED_AGENT_MENTION_NAME promotes it to lastInsertedAgentMention*
121
+ * and fires a public dispatch. Consumers should react only to lastInsertedAgentMention*.
122
+ */
123
+ pendingPastedAgentMention?: {
124
+ context: DocNode;
125
+ id: string;
126
+ localId: string;
127
+ parentNodeType: string | null;
128
+ prompt: string | null;
129
+ } | null;
117
130
  /**
118
131
  * @internal Tracks a typed agent mention while waiting for the platform-side
119
132
  * ready-to-fire trigger. Consumers should continue to react only to
@@ -140,6 +153,6 @@ export type MentionPluginState = {
140
153
  } | null;
141
154
  };
142
155
  export type FireElementsChannelEvent = (payload: AnalyticsEventPayload, channel?: string) => void;
143
- export type MentionSharedState = MentionPluginState & {
156
+ export type MentionSharedState = Omit<MentionPluginState, 'pendingPastedAgentMention'> & {
144
157
  typeAheadHandler: TypeAheadHandler;
145
158
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "14.6.3",
3
+ "version": "14.6.5",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -37,11 +37,11 @@
37
37
  "@atlaskit/platform-feature-flags": "^2.0.0",
38
38
  "@atlaskit/popper": "^8.3.0",
39
39
  "@atlaskit/portal": "^6.1.0",
40
- "@atlaskit/primitives": "^20.6.0",
40
+ "@atlaskit/primitives": "^21.0.0",
41
41
  "@atlaskit/profilecard": "^26.9.0",
42
42
  "@atlaskit/teams-app-config": "^2.1.0",
43
43
  "@atlaskit/theme": "^26.1.0",
44
- "@atlaskit/tmp-editor-statsig": "^125.0.0",
44
+ "@atlaskit/tmp-editor-statsig": "^125.2.0",
45
45
  "@atlaskit/tokens": "^15.8.0",
46
46
  "@atlaskit/tooltip": "^23.1.0",
47
47
  "@atlaskit/user-picker": "^13.4.0",