@atlaskit/editor-plugin-mentions 14.5.8 → 14.5.10

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,24 @@
1
1
  # @atlaskit/editor-plugin-mentions
2
2
 
3
+ ## 14.5.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [`1448830a87645`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1448830a87645) -
8
+ Preserve ADF-backed editor agent mention prompt context through Rovo chat drafts and sends.
9
+ - Updated dependencies
10
+
11
+ ## 14.5.9
12
+
13
+ ### Patch Changes
14
+
15
+ - [`25b1301af566b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/25b1301af566b) -
16
+ [ux] Make Labs lozenge text capitalised
17
+ - [`d2f1039e54388`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d2f1039e54388) -
18
+ Defer typed agent mention nudges while focus remains in the active document but outside the
19
+ editor, such as when typeahead, date, or status picker UI is open.
20
+ - Updated dependencies
21
+
3
22
  ## 14.5.8
4
23
 
5
24
  ### Patch Changes
package/compass.yml CHANGED
@@ -24,6 +24,9 @@ customFields:
24
24
  - name: Department
25
25
  type: text
26
26
  value: Eng - Editor AI
27
+ - name: Trusted Reviewer Teams
28
+ type: text
29
+ value: ari:cloud:identity::team/cf6a670b-5252-4c68-a769-9207de366beb
27
30
  - name: Technical Owner
28
31
  type: user
29
32
  value: ari:cloud:identity::user/612646c53fe26c00694fbe6a # Chris Kimber
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAgentMentionParentContext = void 0;
7
+ var PASS_THROUGH_PROMPT_INLINE_NODE_TYPES = new Set(['hardBreak', 'inlineCard', 'mention', 'text']);
8
+ var isAgentMention = function isAgentMention(node) {
9
+ var _node$attrs;
10
+ return node.type === 'mention' && ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.userType) === 'APP';
11
+ };
12
+ var isAllowedAgentMention = function isAllowedAgentMention(node, agentMentionLocalId) {
13
+ var _node$attrs2;
14
+ return !isAgentMention(node) || ((_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId) === agentMentionLocalId;
15
+ };
16
+ var getStatusText = function getStatusText(node) {
17
+ var _node$attrs3;
18
+ var text = (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.text;
19
+ return typeof text === 'string' && text ? text : null;
20
+ };
21
+ var getDateText = function getDateText(node) {
22
+ var _node$attrs4;
23
+ var timestamp = (_node$attrs4 = node.attrs) === null || _node$attrs4 === void 0 ? void 0 : _node$attrs4.timestamp;
24
+ if (typeof timestamp !== 'string' || !timestamp) {
25
+ return null;
26
+ }
27
+ var date = new Date(Number(timestamp));
28
+ if (Number.isNaN(date.getTime())) {
29
+ return null;
30
+ }
31
+ return date.toISOString().slice(0, 10);
32
+ };
33
+ var toPromptInlineNode = function toPromptInlineNode(node, agentMentionLocalId) {
34
+ if (!isAllowedAgentMention(node, agentMentionLocalId)) {
35
+ return null;
36
+ }
37
+ if (PASS_THROUGH_PROMPT_INLINE_NODE_TYPES.has(node.type)) {
38
+ return node;
39
+ }
40
+ if (node.type === 'status') {
41
+ var text = getStatusText(node);
42
+ return text ? {
43
+ type: 'text',
44
+ text: text
45
+ } : null;
46
+ }
47
+ if (node.type === 'date') {
48
+ var _text = getDateText(node);
49
+ return _text ? {
50
+ type: 'text',
51
+ text: _text
52
+ } : null;
53
+ }
54
+ return null;
55
+ };
56
+
57
+ /**
58
+ * Returns the direct parent content of an inserted agent mention as prompt ADF.
59
+ *
60
+ * The chat input supports only a subset of editor inline ADF, so this keeps prompt content
61
+ * intentionally narrow:
62
+ * - `text`, `inlineCard`, and `hardBreak` pass through unchanged.
63
+ * - people mentions pass through unchanged.
64
+ * - only the invoked agent mention is kept, identified by `localId`; other agent mentions are dropped.
65
+ * - `status` becomes its label text.
66
+ * - `date` becomes ISO date text.
67
+ * - everything else is dropped.
68
+ *
69
+ * This only reads direct parent content. It does not recursively pull content out of nested or
70
+ * unsupported nodes.
71
+ */
72
+ var getAgentMentionParentContext = exports.getAgentMentionParentContext = function getAgentMentionParentContext(parentNode, agentMentionLocalId) {
73
+ var _parentAdf$content;
74
+ var parentAdf = parentNode.toJSON();
75
+ var supportedInlineContent = ((_parentAdf$content = parentAdf.content) !== null && _parentAdf$content !== void 0 ? _parentAdf$content : []).flatMap(function (node) {
76
+ var promptNode = toPromptInlineNode(node, agentMentionLocalId);
77
+ return promptNode ? [promptNode] : [];
78
+ });
79
+ return {
80
+ type: 'doc',
81
+ version: 1,
82
+ content: [{
83
+ type: 'paragraph',
84
+ content: supportedInlineContent
85
+ }]
86
+ };
87
+ };
@@ -17,6 +17,7 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
17
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
18
18
  var _mentionNodeView = require("../nodeviews/mentionNodeView");
19
19
  var _types2 = require("../types");
20
+ var _agentMentionContext = require("./agent-mention-context");
20
21
  var _key = require("./key");
21
22
  var _utils = require("./utils");
22
23
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
@@ -49,8 +50,9 @@ var getAgentMentionName = function getAgentMentionName(text, fallbackName) {
49
50
  };
50
51
  var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
51
52
  var AGENT_MENTION_INACTIVITY_MS = 3000;
53
+ var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
52
54
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
53
- var PACKAGE_VERSION = "14.5.7";
55
+ var PACKAGE_VERSION = "14.5.9";
54
56
  var setProvider = function setProvider(provider) {
55
57
  return function (state, dispatch) {
56
58
  if (dispatch) {
@@ -102,11 +104,14 @@ var getAgentMentionDetailsAtPos = function getAgentMentionDetailsAtPos(state, po
102
104
  }
103
105
  var $mentionPos = state.doc.resolve(Math.min(pos + node.nodeSize, state.doc.content.size));
104
106
  var parentNode = $mentionPos.node($mentionPos.depth);
107
+ var id = node.attrs.id;
108
+ var name = getAgentMentionName(node.attrs.text, fallbackName);
105
109
  return {
106
- id: node.attrs.id,
110
+ id: id,
107
111
  localId: node.attrs.localId,
108
- context: parentNode.textContent.trim() || null,
109
- name: getAgentMentionName(node.attrs.text, fallbackName),
112
+ context: (0, _agentMentionContext.getAgentMentionParentContext)(parentNode, node.attrs.localId),
113
+ name: name,
114
+ prompt: parentNode.textContent.trim() || null,
110
115
  nodeSize: node.nodeSize,
111
116
  parentEnd: $mentionPos.end($mentionPos.depth),
112
117
  parentNodeType: (_parentNode$type$name = parentNode.type.name) !== null && _parentNode$type$name !== void 0 ? _parentNode$type$name : null,
@@ -195,6 +200,7 @@ var commitResolvedPendingTypedAgentMention = function commitResolvedPendingTyped
195
200
  lastInsertedAgentMentionLocalId: pendingMentionDetails.localId,
196
201
  lastInsertedAgentMentionContext: pendingMentionDetails.context,
197
202
  lastInsertedAgentMentionName: pendingMentionDetails.name,
203
+ lastInsertedAgentMentionPrompt: pendingMentionDetails.prompt,
198
204
  lastInsertedAgentMentionParentNodeType: pendingMentionDetails.parentNodeType,
199
205
  lastAgentMentionInsertionCount: ((_pluginState$lastAgen = pluginState.lastAgentMentionInsertionCount) !== null && _pluginState$lastAgen !== void 0 ? _pluginState$lastAgen : 0) + 1
200
206
  })
@@ -221,7 +227,7 @@ var commitPendingTypedAgentMention = function commitPendingTypedAgentMention(sta
221
227
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
222
228
  };
223
229
  var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginState) {
224
- return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
230
+ return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
225
231
  };
226
232
 
227
233
  /**
@@ -236,6 +242,7 @@ var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(plugi
236
242
  lastInsertedAgentMentionLocalId: null,
237
243
  lastInsertedAgentMentionContext: null,
238
244
  lastInsertedAgentMentionName: null,
245
+ lastInsertedAgentMentionPrompt: null,
239
246
  lastInsertedAgentMentionParentNodeType: null
240
247
  });
241
248
  };
@@ -425,6 +432,7 @@ function createMentionPlugin(_ref2) {
425
432
  var agentMentionLocalId = null;
426
433
  var agentMentionContext = null;
427
434
  var agentMentionName = null;
435
+ var agentMentionPrompt = null;
428
436
  var agentMentionParentNodeType = null;
429
437
  var existingAgentMentionLocalIdsInChangedRanges = new Set();
430
438
  var pendingTypedAgentMentionDetails = null;
@@ -456,6 +464,7 @@ function createMentionPlugin(_ref2) {
456
464
  agentMentionLocalId = agentMentionDetails.localId;
457
465
  agentMentionContext = agentMentionDetails.context;
458
466
  agentMentionName = agentMentionDetails.name;
467
+ agentMentionPrompt = agentMentionDetails.prompt;
459
468
  agentMentionParentNodeType = agentMentionDetails.parentNodeType;
460
469
  }
461
470
  }
@@ -504,6 +513,7 @@ function createMentionPlugin(_ref2) {
504
513
  agentMentionLocalId = survivorDetails.localId;
505
514
  agentMentionContext = survivorDetails.context;
506
515
  agentMentionName = survivorDetails.name;
516
+ agentMentionPrompt = survivorDetails.prompt;
507
517
  agentMentionParentNodeType = survivorDetails.parentNodeType;
508
518
  resolvedFromFullDocFallback = true;
509
519
  }
@@ -552,17 +562,19 @@ function createMentionPlugin(_ref2) {
552
562
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
553
563
  lastInsertedAgentMentionContext: agentMentionContext,
554
564
  lastInsertedAgentMentionName: agentMentionName,
565
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
555
566
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
556
567
  }, newInsertionCount !== undefined ? {
557
568
  lastAgentMentionInsertionCount: newInsertionCount
558
569
  } : {});
559
570
  hasPublicPluginStateChanged = true;
560
- } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionContext !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionContext) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionName !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
571
+ } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionName !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionPrompt !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionPrompt) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
561
572
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
562
573
  lastInsertedAgentMentionId: agentMentionId,
563
574
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
564
575
  lastInsertedAgentMentionContext: agentMentionContext,
565
576
  lastInsertedAgentMentionName: agentMentionName,
577
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
566
578
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
567
579
  }, newInsertionCount !== undefined ? {
568
580
  lastAgentMentionInsertionCount: newInsertionCount
@@ -624,14 +636,47 @@ function createMentionPlugin(_ref2) {
624
636
  var isAgentMentionsEnabled = (0, _experiments.editorExperiment)('platform_editor_agent_mentions', true);
625
637
  var pendingTypedAgentMentionTimer;
626
638
  var pendingTypedAgentMentionTimerKey = null;
639
+ var pendingTypedAgentMentionFocusDeferCount = 0;
640
+
641
+ /**
642
+ * Clears the currently scheduled pending typed-agent-mention timer.
643
+ *
644
+ * By default this also resets the focus defer count because a new pending mention,
645
+ * local edit reset, or cleanup should start a fresh escape-hatch window. Focus-based
646
+ * retries pass `preserveFocusDeferCount` so repeated defers for the same pending
647
+ * mention are counted toward the bounded retry cap.
648
+ */
627
649
  var clearPendingTypedAgentMentionTimer = function clearPendingTypedAgentMentionTimer() {
650
+ var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
651
+ _ref4$preserveFocusDe = _ref4.preserveFocusDeferCount,
652
+ preserveFocusDeferCount = _ref4$preserveFocusDe === void 0 ? false : _ref4$preserveFocusDe;
628
653
  if (pendingTypedAgentMentionTimer) {
629
654
  clearTimeout(pendingTypedAgentMentionTimer);
630
655
  pendingTypedAgentMentionTimer = undefined;
631
656
  }
632
657
  pendingTypedAgentMentionTimerKey = null;
658
+ if (!preserveFocusDeferCount) {
659
+ pendingTypedAgentMentionFocusDeferCount = 0;
660
+ }
661
+ };
662
+
663
+ /**
664
+ * Typed agent mentions intentionally wait before invoking the agent so content the
665
+ * user adds next can become context. That context can be authored through
666
+ * editor-adjacent UI, such as mention typeahead, date picker, or status picker,
667
+ * where focus leaves the ProseMirror editor but remains in the active document.
668
+ * Treat that as continued authoring activity by restarting the inactivity window.
669
+ * This only defers the inactivity timer path: existing selection-change handling can
670
+ * still publish or clear the pending mention sooner. After 20 focus defers (~1 minute),
671
+ * publish anyway so pathological focus states cannot keep the mention pending indefinitely.
672
+ */
673
+ var shouldDeferPendingTypedAgentMention = function shouldDeferPendingTypedAgentMention() {
674
+ return typeof document !== 'undefined' && document.hasFocus() && !editorView.hasFocus();
633
675
  };
634
- var schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
676
+ var _schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
677
+ var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
678
+ _ref5$preserveFocusDe = _ref5.preserveFocusDeferCount,
679
+ preserveFocusDeferCount = _ref5$preserveFocusDe === void 0 ? false : _ref5$preserveFocusDe;
635
680
  if (!isAgentMentionsEnabled) {
636
681
  clearPendingTypedAgentMentionTimer();
637
682
  return;
@@ -645,7 +690,9 @@ function createMentionPlugin(_ref2) {
645
690
  if (timerKey === pendingTypedAgentMentionTimerKey) {
646
691
  return;
647
692
  }
648
- clearPendingTypedAgentMentionTimer();
693
+ clearPendingTypedAgentMentionTimer({
694
+ preserveFocusDeferCount: preserveFocusDeferCount
695
+ });
649
696
  pendingTypedAgentMentionTimerKey = timerKey;
650
697
  pendingTypedAgentMentionTimer = setTimeout(function () {
651
698
  var _mentionPluginKey$get;
@@ -653,6 +700,15 @@ function createMentionPlugin(_ref2) {
653
700
  if (!latestPendingTypedAgentMention || latestPendingTypedAgentMention.localId !== pendingTypedAgentMention.localId || latestPendingTypedAgentMention.resetCount !== pendingTypedAgentMention.resetCount) {
654
701
  return;
655
702
  }
703
+ if (shouldDeferPendingTypedAgentMention() && pendingTypedAgentMentionFocusDeferCount < MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS) {
704
+ pendingTypedAgentMentionFocusDeferCount++;
705
+ pendingTypedAgentMentionTimerKey = null;
706
+ _schedulePendingTypedAgentMentionTimer(_key.mentionPluginKey.getState(editorView.state), {
707
+ preserveFocusDeferCount: true
708
+ });
709
+ return;
710
+ }
711
+ pendingTypedAgentMentionFocusDeferCount = 0;
656
712
  editorView.dispatch(editorView.state.tr.setMeta(_key.mentionPluginKey, {
657
713
  action: ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION,
658
714
  params: {
@@ -712,7 +768,7 @@ function createMentionPlugin(_ref2) {
712
768
  if (mentionPluginState === _key.mentionPluginKey.getState(prevState)) {
713
769
  return;
714
770
  }
715
- schedulePendingTypedAgentMentionTimer(mentionPluginState);
771
+ _schedulePendingTypedAgentMentionTimer(mentionPluginState);
716
772
  },
717
773
  destroy: function destroy() {
718
774
  clearPendingTypedAgentMentionTimer();
@@ -399,7 +399,7 @@ var createTypeAheadConfig = exports.createTypeAheadConfig = function createTypeA
399
399
  } : {}), (0, _expVal.expVal)('platform_editor_agent_mentions', 'isEnabled', false) ? {
400
400
  lozenge: /*#__PURE__*/_react.default.createElement(_lozenge.default, {
401
401
  appearance: "new"
402
- }, intl.formatMessage(_messages.mentionMessages.typeAheadSectionAgentsLabs))
402
+ }, intl.formatMessage(_messages.mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
403
403
  } : {})];
404
404
  },
405
405
  onOpen: function onOpen() {
@@ -0,0 +1,81 @@
1
+ const PASS_THROUGH_PROMPT_INLINE_NODE_TYPES = new Set(['hardBreak', 'inlineCard', 'mention', 'text']);
2
+ const isAgentMention = node => {
3
+ var _node$attrs;
4
+ return node.type === 'mention' && ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.userType) === 'APP';
5
+ };
6
+ const isAllowedAgentMention = (node, agentMentionLocalId) => {
7
+ var _node$attrs2;
8
+ return !isAgentMention(node) || ((_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId) === agentMentionLocalId;
9
+ };
10
+ const getStatusText = node => {
11
+ var _node$attrs3;
12
+ const text = (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.text;
13
+ return typeof text === 'string' && text ? text : null;
14
+ };
15
+ const getDateText = node => {
16
+ var _node$attrs4;
17
+ const timestamp = (_node$attrs4 = node.attrs) === null || _node$attrs4 === void 0 ? void 0 : _node$attrs4.timestamp;
18
+ if (typeof timestamp !== 'string' || !timestamp) {
19
+ return null;
20
+ }
21
+ const date = new Date(Number(timestamp));
22
+ if (Number.isNaN(date.getTime())) {
23
+ return null;
24
+ }
25
+ return date.toISOString().slice(0, 10);
26
+ };
27
+ const toPromptInlineNode = (node, agentMentionLocalId) => {
28
+ if (!isAllowedAgentMention(node, agentMentionLocalId)) {
29
+ return null;
30
+ }
31
+ if (PASS_THROUGH_PROMPT_INLINE_NODE_TYPES.has(node.type)) {
32
+ return node;
33
+ }
34
+ if (node.type === 'status') {
35
+ const text = getStatusText(node);
36
+ return text ? {
37
+ type: 'text',
38
+ text
39
+ } : null;
40
+ }
41
+ if (node.type === 'date') {
42
+ const text = getDateText(node);
43
+ return text ? {
44
+ type: 'text',
45
+ text
46
+ } : null;
47
+ }
48
+ return null;
49
+ };
50
+
51
+ /**
52
+ * Returns the direct parent content of an inserted agent mention as prompt ADF.
53
+ *
54
+ * The chat input supports only a subset of editor inline ADF, so this keeps prompt content
55
+ * intentionally narrow:
56
+ * - `text`, `inlineCard`, and `hardBreak` pass through unchanged.
57
+ * - people mentions pass through unchanged.
58
+ * - only the invoked agent mention is kept, identified by `localId`; other agent mentions are dropped.
59
+ * - `status` becomes its label text.
60
+ * - `date` becomes ISO date text.
61
+ * - everything else is dropped.
62
+ *
63
+ * This only reads direct parent content. It does not recursively pull content out of nested or
64
+ * unsupported nodes.
65
+ */
66
+ export const getAgentMentionParentContext = (parentNode, agentMentionLocalId) => {
67
+ var _parentAdf$content;
68
+ const parentAdf = parentNode.toJSON();
69
+ const supportedInlineContent = ((_parentAdf$content = parentAdf.content) !== null && _parentAdf$content !== void 0 ? _parentAdf$content : []).flatMap(node => {
70
+ const promptNode = toPromptInlineNode(node, agentMentionLocalId);
71
+ return promptNode ? [promptNode] : [];
72
+ });
73
+ return {
74
+ type: 'doc',
75
+ version: 1,
76
+ content: [{
77
+ type: 'paragraph',
78
+ content: supportedInlineContent
79
+ }]
80
+ };
81
+ };
@@ -7,6 +7,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
8
8
  import { MentionNodeView } from '../nodeviews/mentionNodeView';
9
9
  import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
10
+ import { getAgentMentionParentContext } from './agent-mention-context';
10
11
  import { mentionPluginKey } from './key';
11
12
  import { canMentionBeCreatedInRange } from './utils';
12
13
  export const ACTIONS = {
@@ -34,8 +35,9 @@ const getAgentMentionName = (text, fallbackName) => {
34
35
  };
35
36
  const AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
36
37
  const AGENT_MENTION_INACTIVITY_MS = 3000;
38
+ const MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
37
39
  const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
38
- const PACKAGE_VERSION = "14.5.7";
40
+ const PACKAGE_VERSION = "14.5.9";
39
41
  const setProvider = provider => (state, dispatch) => {
40
42
  if (dispatch) {
41
43
  dispatch(state.tr.setMeta(mentionPluginKey, {
@@ -85,11 +87,14 @@ const getAgentMentionDetailsAtPos = (state, pos, matchesMention, fallbackName) =
85
87
  }
86
88
  const $mentionPos = state.doc.resolve(Math.min(pos + node.nodeSize, state.doc.content.size));
87
89
  const parentNode = $mentionPos.node($mentionPos.depth);
90
+ const id = node.attrs.id;
91
+ const name = getAgentMentionName(node.attrs.text, fallbackName);
88
92
  return {
89
- id: node.attrs.id,
93
+ id,
90
94
  localId: node.attrs.localId,
91
- context: parentNode.textContent.trim() || null,
92
- name: getAgentMentionName(node.attrs.text, fallbackName),
95
+ context: getAgentMentionParentContext(parentNode, node.attrs.localId),
96
+ name,
97
+ prompt: parentNode.textContent.trim() || null,
93
98
  nodeSize: node.nodeSize,
94
99
  parentEnd: $mentionPos.end($mentionPos.depth),
95
100
  parentNodeType: (_parentNode$type$name = parentNode.type.name) !== null && _parentNode$type$name !== void 0 ? _parentNode$type$name : null,
@@ -174,6 +179,7 @@ const commitResolvedPendingTypedAgentMention = (pluginState, pendingMentionDetai
174
179
  lastInsertedAgentMentionLocalId: pendingMentionDetails.localId,
175
180
  lastInsertedAgentMentionContext: pendingMentionDetails.context,
176
181
  lastInsertedAgentMentionName: pendingMentionDetails.name,
182
+ lastInsertedAgentMentionPrompt: pendingMentionDetails.prompt,
177
183
  lastInsertedAgentMentionParentNodeType: pendingMentionDetails.parentNodeType,
178
184
  lastAgentMentionInsertionCount: ((_pluginState$lastAgen = pluginState.lastAgentMentionInsertionCount) !== null && _pluginState$lastAgen !== void 0 ? _pluginState$lastAgen : 0) + 1
179
185
  }
@@ -198,7 +204,7 @@ const commitPendingTypedAgentMention = (state, pluginState, pendingTypedAgentMen
198
204
  }
199
205
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
200
206
  };
201
- const hasTrackedAgentMentionState = pluginState => Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
207
+ const hasTrackedAgentMentionState = pluginState => Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
202
208
 
203
209
  /**
204
210
  * Clears agent mention state that points at a specific document snapshot.
@@ -213,6 +219,7 @@ const clearTrackedAgentMentionState = pluginState => {
213
219
  lastInsertedAgentMentionLocalId: null,
214
220
  lastInsertedAgentMentionContext: null,
215
221
  lastInsertedAgentMentionName: null,
222
+ lastInsertedAgentMentionPrompt: null,
216
223
  lastInsertedAgentMentionParentNodeType: null
217
224
  };
218
225
  };
@@ -405,6 +412,7 @@ export function createMentionPlugin({
405
412
  let agentMentionLocalId = null;
406
413
  let agentMentionContext = null;
407
414
  let agentMentionName = null;
415
+ let agentMentionPrompt = null;
408
416
  let agentMentionParentNodeType = null;
409
417
  const existingAgentMentionLocalIdsInChangedRanges = new Set();
410
418
  let pendingTypedAgentMentionDetails = null;
@@ -426,6 +434,7 @@ export function createMentionPlugin({
426
434
  agentMentionLocalId = agentMentionDetails.localId;
427
435
  agentMentionContext = agentMentionDetails.context;
428
436
  agentMentionName = agentMentionDetails.name;
437
+ agentMentionPrompt = agentMentionDetails.prompt;
429
438
  agentMentionParentNodeType = agentMentionDetails.parentNodeType;
430
439
  }
431
440
  }
@@ -458,6 +467,7 @@ export function createMentionPlugin({
458
467
  agentMentionLocalId = survivorDetails.localId;
459
468
  agentMentionContext = survivorDetails.context;
460
469
  agentMentionName = survivorDetails.name;
470
+ agentMentionPrompt = survivorDetails.prompt;
461
471
  agentMentionParentNodeType = survivorDetails.parentNodeType;
462
472
  resolvedFromFullDocFallback = true;
463
473
  }
@@ -508,19 +518,21 @@ export function createMentionPlugin({
508
518
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
509
519
  lastInsertedAgentMentionContext: agentMentionContext,
510
520
  lastInsertedAgentMentionName: agentMentionName,
521
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
511
522
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType,
512
523
  ...(newInsertionCount !== undefined ? {
513
524
  lastAgentMentionInsertionCount: newInsertionCount
514
525
  } : {})
515
526
  };
516
527
  hasPublicPluginStateChanged = true;
517
- } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionContext !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionContext) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionName !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
528
+ } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionName !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionPrompt !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionPrompt) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
518
529
  newPluginState = {
519
530
  ...newPluginState,
520
531
  lastInsertedAgentMentionId: agentMentionId,
521
532
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
522
533
  lastInsertedAgentMentionContext: agentMentionContext,
523
534
  lastInsertedAgentMentionName: agentMentionName,
535
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
524
536
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType,
525
537
  ...(newInsertionCount !== undefined ? {
526
538
  lastAgentMentionInsertionCount: newInsertionCount
@@ -583,14 +595,43 @@ export function createMentionPlugin({
583
595
  const isAgentMentionsEnabled = editorExperiment('platform_editor_agent_mentions', true);
584
596
  let pendingTypedAgentMentionTimer;
585
597
  let pendingTypedAgentMentionTimerKey = null;
586
- const clearPendingTypedAgentMentionTimer = () => {
598
+ let pendingTypedAgentMentionFocusDeferCount = 0;
599
+
600
+ /**
601
+ * Clears the currently scheduled pending typed-agent-mention timer.
602
+ *
603
+ * By default this also resets the focus defer count because a new pending mention,
604
+ * local edit reset, or cleanup should start a fresh escape-hatch window. Focus-based
605
+ * retries pass `preserveFocusDeferCount` so repeated defers for the same pending
606
+ * mention are counted toward the bounded retry cap.
607
+ */
608
+ const clearPendingTypedAgentMentionTimer = ({
609
+ preserveFocusDeferCount = false
610
+ } = {}) => {
587
611
  if (pendingTypedAgentMentionTimer) {
588
612
  clearTimeout(pendingTypedAgentMentionTimer);
589
613
  pendingTypedAgentMentionTimer = undefined;
590
614
  }
591
615
  pendingTypedAgentMentionTimerKey = null;
616
+ if (!preserveFocusDeferCount) {
617
+ pendingTypedAgentMentionFocusDeferCount = 0;
618
+ }
592
619
  };
593
- const schedulePendingTypedAgentMentionTimer = mentionPluginState => {
620
+
621
+ /**
622
+ * Typed agent mentions intentionally wait before invoking the agent so content the
623
+ * user adds next can become context. That context can be authored through
624
+ * editor-adjacent UI, such as mention typeahead, date picker, or status picker,
625
+ * where focus leaves the ProseMirror editor but remains in the active document.
626
+ * Treat that as continued authoring activity by restarting the inactivity window.
627
+ * This only defers the inactivity timer path: existing selection-change handling can
628
+ * still publish or clear the pending mention sooner. After 20 focus defers (~1 minute),
629
+ * publish anyway so pathological focus states cannot keep the mention pending indefinitely.
630
+ */
631
+ const shouldDeferPendingTypedAgentMention = () => typeof document !== 'undefined' && document.hasFocus() && !editorView.hasFocus();
632
+ const schedulePendingTypedAgentMentionTimer = (mentionPluginState, {
633
+ preserveFocusDeferCount = false
634
+ } = {}) => {
594
635
  if (!isAgentMentionsEnabled) {
595
636
  clearPendingTypedAgentMentionTimer();
596
637
  return;
@@ -604,7 +645,9 @@ export function createMentionPlugin({
604
645
  if (timerKey === pendingTypedAgentMentionTimerKey) {
605
646
  return;
606
647
  }
607
- clearPendingTypedAgentMentionTimer();
648
+ clearPendingTypedAgentMentionTimer({
649
+ preserveFocusDeferCount
650
+ });
608
651
  pendingTypedAgentMentionTimerKey = timerKey;
609
652
  pendingTypedAgentMentionTimer = setTimeout(() => {
610
653
  var _mentionPluginKey$get;
@@ -612,6 +655,15 @@ export function createMentionPlugin({
612
655
  if (!latestPendingTypedAgentMention || latestPendingTypedAgentMention.localId !== pendingTypedAgentMention.localId || latestPendingTypedAgentMention.resetCount !== pendingTypedAgentMention.resetCount) {
613
656
  return;
614
657
  }
658
+ if (shouldDeferPendingTypedAgentMention() && pendingTypedAgentMentionFocusDeferCount < MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS) {
659
+ pendingTypedAgentMentionFocusDeferCount++;
660
+ pendingTypedAgentMentionTimerKey = null;
661
+ schedulePendingTypedAgentMentionTimer(mentionPluginKey.getState(editorView.state), {
662
+ preserveFocusDeferCount: true
663
+ });
664
+ return;
665
+ }
666
+ pendingTypedAgentMentionFocusDeferCount = 0;
615
667
  editorView.dispatch(editorView.state.tr.setMeta(mentionPluginKey, {
616
668
  action: ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION,
617
669
  params: {
@@ -373,7 +373,7 @@ export const createTypeAheadConfig = ({
373
373
  ...(expVal('platform_editor_agent_mentions', 'isEnabled', false) ? {
374
374
  lozenge: /*#__PURE__*/React.createElement(Lozenge, {
375
375
  appearance: "new"
376
- }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabs))
376
+ }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
377
377
  } : {})
378
378
  }];
379
379
  },
@@ -0,0 +1,81 @@
1
+ var PASS_THROUGH_PROMPT_INLINE_NODE_TYPES = new Set(['hardBreak', 'inlineCard', 'mention', 'text']);
2
+ var isAgentMention = function isAgentMention(node) {
3
+ var _node$attrs;
4
+ return node.type === 'mention' && ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.userType) === 'APP';
5
+ };
6
+ var isAllowedAgentMention = function isAllowedAgentMention(node, agentMentionLocalId) {
7
+ var _node$attrs2;
8
+ return !isAgentMention(node) || ((_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId) === agentMentionLocalId;
9
+ };
10
+ var getStatusText = function getStatusText(node) {
11
+ var _node$attrs3;
12
+ var text = (_node$attrs3 = node.attrs) === null || _node$attrs3 === void 0 ? void 0 : _node$attrs3.text;
13
+ return typeof text === 'string' && text ? text : null;
14
+ };
15
+ var getDateText = function getDateText(node) {
16
+ var _node$attrs4;
17
+ var timestamp = (_node$attrs4 = node.attrs) === null || _node$attrs4 === void 0 ? void 0 : _node$attrs4.timestamp;
18
+ if (typeof timestamp !== 'string' || !timestamp) {
19
+ return null;
20
+ }
21
+ var date = new Date(Number(timestamp));
22
+ if (Number.isNaN(date.getTime())) {
23
+ return null;
24
+ }
25
+ return date.toISOString().slice(0, 10);
26
+ };
27
+ var toPromptInlineNode = function toPromptInlineNode(node, agentMentionLocalId) {
28
+ if (!isAllowedAgentMention(node, agentMentionLocalId)) {
29
+ return null;
30
+ }
31
+ if (PASS_THROUGH_PROMPT_INLINE_NODE_TYPES.has(node.type)) {
32
+ return node;
33
+ }
34
+ if (node.type === 'status') {
35
+ var text = getStatusText(node);
36
+ return text ? {
37
+ type: 'text',
38
+ text: text
39
+ } : null;
40
+ }
41
+ if (node.type === 'date') {
42
+ var _text = getDateText(node);
43
+ return _text ? {
44
+ type: 'text',
45
+ text: _text
46
+ } : null;
47
+ }
48
+ return null;
49
+ };
50
+
51
+ /**
52
+ * Returns the direct parent content of an inserted agent mention as prompt ADF.
53
+ *
54
+ * The chat input supports only a subset of editor inline ADF, so this keeps prompt content
55
+ * intentionally narrow:
56
+ * - `text`, `inlineCard`, and `hardBreak` pass through unchanged.
57
+ * - people mentions pass through unchanged.
58
+ * - only the invoked agent mention is kept, identified by `localId`; other agent mentions are dropped.
59
+ * - `status` becomes its label text.
60
+ * - `date` becomes ISO date text.
61
+ * - everything else is dropped.
62
+ *
63
+ * This only reads direct parent content. It does not recursively pull content out of nested or
64
+ * unsupported nodes.
65
+ */
66
+ export var getAgentMentionParentContext = function getAgentMentionParentContext(parentNode, agentMentionLocalId) {
67
+ var _parentAdf$content;
68
+ var parentAdf = parentNode.toJSON();
69
+ var supportedInlineContent = ((_parentAdf$content = parentAdf.content) !== null && _parentAdf$content !== void 0 ? _parentAdf$content : []).flatMap(function (node) {
70
+ var promptNode = toPromptInlineNode(node, agentMentionLocalId);
71
+ return promptNode ? [promptNode] : [];
72
+ });
73
+ return {
74
+ type: 'doc',
75
+ version: 1,
76
+ content: [{
77
+ type: 'paragraph',
78
+ content: supportedInlineContent
79
+ }]
80
+ };
81
+ };
@@ -14,6 +14,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
14
14
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
15
15
  import { MentionNodeView } from '../nodeviews/mentionNodeView';
16
16
  import { MENTION_PROVIDER_REJECTED, MENTION_PROVIDER_UNDEFINED } from '../types';
17
+ import { getAgentMentionParentContext } from './agent-mention-context';
17
18
  import { mentionPluginKey } from './key';
18
19
  import { canMentionBeCreatedInRange } from './utils';
19
20
  export var ACTIONS = {
@@ -41,8 +42,9 @@ var getAgentMentionName = function getAgentMentionName(text, fallbackName) {
41
42
  };
42
43
  var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
43
44
  var AGENT_MENTION_INACTIVITY_MS = 3000;
45
+ var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
44
46
  var PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
45
- var PACKAGE_VERSION = "14.5.7";
47
+ var PACKAGE_VERSION = "14.5.9";
46
48
  var setProvider = function setProvider(provider) {
47
49
  return function (state, dispatch) {
48
50
  if (dispatch) {
@@ -94,11 +96,14 @@ var getAgentMentionDetailsAtPos = function getAgentMentionDetailsAtPos(state, po
94
96
  }
95
97
  var $mentionPos = state.doc.resolve(Math.min(pos + node.nodeSize, state.doc.content.size));
96
98
  var parentNode = $mentionPos.node($mentionPos.depth);
99
+ var id = node.attrs.id;
100
+ var name = getAgentMentionName(node.attrs.text, fallbackName);
97
101
  return {
98
- id: node.attrs.id,
102
+ id: id,
99
103
  localId: node.attrs.localId,
100
- context: parentNode.textContent.trim() || null,
101
- name: getAgentMentionName(node.attrs.text, fallbackName),
104
+ context: getAgentMentionParentContext(parentNode, node.attrs.localId),
105
+ name: name,
106
+ prompt: parentNode.textContent.trim() || null,
102
107
  nodeSize: node.nodeSize,
103
108
  parentEnd: $mentionPos.end($mentionPos.depth),
104
109
  parentNodeType: (_parentNode$type$name = parentNode.type.name) !== null && _parentNode$type$name !== void 0 ? _parentNode$type$name : null,
@@ -187,6 +192,7 @@ var commitResolvedPendingTypedAgentMention = function commitResolvedPendingTyped
187
192
  lastInsertedAgentMentionLocalId: pendingMentionDetails.localId,
188
193
  lastInsertedAgentMentionContext: pendingMentionDetails.context,
189
194
  lastInsertedAgentMentionName: pendingMentionDetails.name,
195
+ lastInsertedAgentMentionPrompt: pendingMentionDetails.prompt,
190
196
  lastInsertedAgentMentionParentNodeType: pendingMentionDetails.parentNodeType,
191
197
  lastAgentMentionInsertionCount: ((_pluginState$lastAgen = pluginState.lastAgentMentionInsertionCount) !== null && _pluginState$lastAgen !== void 0 ? _pluginState$lastAgen : 0) + 1
192
198
  })
@@ -213,7 +219,7 @@ var commitPendingTypedAgentMention = function commitPendingTypedAgentMention(sta
213
219
  return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
214
220
  };
215
221
  var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginState) {
216
- return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
222
+ return Boolean(pluginState.pendingTypedAgentMention) || pluginState.lastInsertedAgentMentionId != null || pluginState.lastInsertedAgentMentionLocalId != null || pluginState.lastInsertedAgentMentionContext != null || pluginState.lastInsertedAgentMentionName != null || pluginState.lastInsertedAgentMentionPrompt != null || pluginState.lastInsertedAgentMentionParentNodeType != null;
217
223
  };
218
224
 
219
225
  /**
@@ -228,6 +234,7 @@ var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(plugi
228
234
  lastInsertedAgentMentionLocalId: null,
229
235
  lastInsertedAgentMentionContext: null,
230
236
  lastInsertedAgentMentionName: null,
237
+ lastInsertedAgentMentionPrompt: null,
231
238
  lastInsertedAgentMentionParentNodeType: null
232
239
  });
233
240
  };
@@ -417,6 +424,7 @@ export function createMentionPlugin(_ref2) {
417
424
  var agentMentionLocalId = null;
418
425
  var agentMentionContext = null;
419
426
  var agentMentionName = null;
427
+ var agentMentionPrompt = null;
420
428
  var agentMentionParentNodeType = null;
421
429
  var existingAgentMentionLocalIdsInChangedRanges = new Set();
422
430
  var pendingTypedAgentMentionDetails = null;
@@ -448,6 +456,7 @@ export function createMentionPlugin(_ref2) {
448
456
  agentMentionLocalId = agentMentionDetails.localId;
449
457
  agentMentionContext = agentMentionDetails.context;
450
458
  agentMentionName = agentMentionDetails.name;
459
+ agentMentionPrompt = agentMentionDetails.prompt;
451
460
  agentMentionParentNodeType = agentMentionDetails.parentNodeType;
452
461
  }
453
462
  }
@@ -496,6 +505,7 @@ export function createMentionPlugin(_ref2) {
496
505
  agentMentionLocalId = survivorDetails.localId;
497
506
  agentMentionContext = survivorDetails.context;
498
507
  agentMentionName = survivorDetails.name;
508
+ agentMentionPrompt = survivorDetails.prompt;
499
509
  agentMentionParentNodeType = survivorDetails.parentNodeType;
500
510
  resolvedFromFullDocFallback = true;
501
511
  }
@@ -544,17 +554,19 @@ export function createMentionPlugin(_ref2) {
544
554
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
545
555
  lastInsertedAgentMentionContext: agentMentionContext,
546
556
  lastInsertedAgentMentionName: agentMentionName,
557
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
547
558
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
548
559
  }, newInsertionCount !== undefined ? {
549
560
  lastAgentMentionInsertionCount: newInsertionCount
550
561
  } : {});
551
562
  hasPublicPluginStateChanged = true;
552
- } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionContext !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionContext) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionName !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
563
+ } else if (agentMentionId !== ((_newPluginState$lastI2 = newPluginState.lastInsertedAgentMentionId) !== null && _newPluginState$lastI2 !== void 0 ? _newPluginState$lastI2 : null) || agentMentionLocalId !== ((_newPluginState$lastI3 = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI3 !== void 0 ? _newPluginState$lastI3 : null) || agentMentionName !== ((_newPluginState$lastI4 = newPluginState.lastInsertedAgentMentionName) !== null && _newPluginState$lastI4 !== void 0 ? _newPluginState$lastI4 : null) || agentMentionPrompt !== ((_newPluginState$lastI5 = newPluginState.lastInsertedAgentMentionPrompt) !== null && _newPluginState$lastI5 !== void 0 ? _newPluginState$lastI5 : null) || agentMentionParentNodeType !== ((_newPluginState$lastI6 = newPluginState.lastInsertedAgentMentionParentNodeType) !== null && _newPluginState$lastI6 !== void 0 ? _newPluginState$lastI6 : null) || newInsertionCount !== undefined) {
553
564
  newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
554
565
  lastInsertedAgentMentionId: agentMentionId,
555
566
  lastInsertedAgentMentionLocalId: agentMentionLocalId,
556
567
  lastInsertedAgentMentionContext: agentMentionContext,
557
568
  lastInsertedAgentMentionName: agentMentionName,
569
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
558
570
  lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
559
571
  }, newInsertionCount !== undefined ? {
560
572
  lastAgentMentionInsertionCount: newInsertionCount
@@ -616,14 +628,47 @@ export function createMentionPlugin(_ref2) {
616
628
  var isAgentMentionsEnabled = editorExperiment('platform_editor_agent_mentions', true);
617
629
  var pendingTypedAgentMentionTimer;
618
630
  var pendingTypedAgentMentionTimerKey = null;
631
+ var pendingTypedAgentMentionFocusDeferCount = 0;
632
+
633
+ /**
634
+ * Clears the currently scheduled pending typed-agent-mention timer.
635
+ *
636
+ * By default this also resets the focus defer count because a new pending mention,
637
+ * local edit reset, or cleanup should start a fresh escape-hatch window. Focus-based
638
+ * retries pass `preserveFocusDeferCount` so repeated defers for the same pending
639
+ * mention are counted toward the bounded retry cap.
640
+ */
619
641
  var clearPendingTypedAgentMentionTimer = function clearPendingTypedAgentMentionTimer() {
642
+ var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
643
+ _ref4$preserveFocusDe = _ref4.preserveFocusDeferCount,
644
+ preserveFocusDeferCount = _ref4$preserveFocusDe === void 0 ? false : _ref4$preserveFocusDe;
620
645
  if (pendingTypedAgentMentionTimer) {
621
646
  clearTimeout(pendingTypedAgentMentionTimer);
622
647
  pendingTypedAgentMentionTimer = undefined;
623
648
  }
624
649
  pendingTypedAgentMentionTimerKey = null;
650
+ if (!preserveFocusDeferCount) {
651
+ pendingTypedAgentMentionFocusDeferCount = 0;
652
+ }
653
+ };
654
+
655
+ /**
656
+ * Typed agent mentions intentionally wait before invoking the agent so content the
657
+ * user adds next can become context. That context can be authored through
658
+ * editor-adjacent UI, such as mention typeahead, date picker, or status picker,
659
+ * where focus leaves the ProseMirror editor but remains in the active document.
660
+ * Treat that as continued authoring activity by restarting the inactivity window.
661
+ * This only defers the inactivity timer path: existing selection-change handling can
662
+ * still publish or clear the pending mention sooner. After 20 focus defers (~1 minute),
663
+ * publish anyway so pathological focus states cannot keep the mention pending indefinitely.
664
+ */
665
+ var shouldDeferPendingTypedAgentMention = function shouldDeferPendingTypedAgentMention() {
666
+ return typeof document !== 'undefined' && document.hasFocus() && !editorView.hasFocus();
625
667
  };
626
- var schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
668
+ var _schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
669
+ var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
670
+ _ref5$preserveFocusDe = _ref5.preserveFocusDeferCount,
671
+ preserveFocusDeferCount = _ref5$preserveFocusDe === void 0 ? false : _ref5$preserveFocusDe;
627
672
  if (!isAgentMentionsEnabled) {
628
673
  clearPendingTypedAgentMentionTimer();
629
674
  return;
@@ -637,7 +682,9 @@ export function createMentionPlugin(_ref2) {
637
682
  if (timerKey === pendingTypedAgentMentionTimerKey) {
638
683
  return;
639
684
  }
640
- clearPendingTypedAgentMentionTimer();
685
+ clearPendingTypedAgentMentionTimer({
686
+ preserveFocusDeferCount: preserveFocusDeferCount
687
+ });
641
688
  pendingTypedAgentMentionTimerKey = timerKey;
642
689
  pendingTypedAgentMentionTimer = setTimeout(function () {
643
690
  var _mentionPluginKey$get;
@@ -645,6 +692,15 @@ export function createMentionPlugin(_ref2) {
645
692
  if (!latestPendingTypedAgentMention || latestPendingTypedAgentMention.localId !== pendingTypedAgentMention.localId || latestPendingTypedAgentMention.resetCount !== pendingTypedAgentMention.resetCount) {
646
693
  return;
647
694
  }
695
+ if (shouldDeferPendingTypedAgentMention() && pendingTypedAgentMentionFocusDeferCount < MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS) {
696
+ pendingTypedAgentMentionFocusDeferCount++;
697
+ pendingTypedAgentMentionTimerKey = null;
698
+ _schedulePendingTypedAgentMentionTimer(mentionPluginKey.getState(editorView.state), {
699
+ preserveFocusDeferCount: true
700
+ });
701
+ return;
702
+ }
703
+ pendingTypedAgentMentionFocusDeferCount = 0;
648
704
  editorView.dispatch(editorView.state.tr.setMeta(mentionPluginKey, {
649
705
  action: ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION,
650
706
  params: {
@@ -704,7 +760,7 @@ export function createMentionPlugin(_ref2) {
704
760
  if (mentionPluginState === mentionPluginKey.getState(prevState)) {
705
761
  return;
706
762
  }
707
- schedulePendingTypedAgentMentionTimer(mentionPluginState);
763
+ _schedulePendingTypedAgentMentionTimer(mentionPluginState);
708
764
  },
709
765
  destroy: function destroy() {
710
766
  clearPendingTypedAgentMentionTimer();
@@ -390,7 +390,7 @@ export var createTypeAheadConfig = function createTypeAheadConfig(_ref8) {
390
390
  } : {}), expVal('platform_editor_agent_mentions', 'isEnabled', false) ? {
391
391
  lozenge: /*#__PURE__*/React.createElement(Lozenge, {
392
392
  appearance: "new"
393
- }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabs))
393
+ }, intl.formatMessage(mentionMessages.typeAheadSectionAgentsLabsLozengeLabel))
394
394
  } : {})];
395
395
  },
396
396
  onOpen: function onOpen() {
@@ -0,0 +1,18 @@
1
+ import type { DocNode } from '@atlaskit/adf-schema';
2
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ /**
4
+ * Returns the direct parent content of an inserted agent mention as prompt ADF.
5
+ *
6
+ * The chat input supports only a subset of editor inline ADF, so this keeps prompt content
7
+ * intentionally narrow:
8
+ * - `text`, `inlineCard`, and `hardBreak` pass through unchanged.
9
+ * - people mentions pass through unchanged.
10
+ * - only the invoked agent mention is kept, identified by `localId`; other agent mentions are dropped.
11
+ * - `status` becomes its label text.
12
+ * - `date` becomes ISO date text.
13
+ * - everything else is dropped.
14
+ *
15
+ * This only reads direct parent content. It does not recursively pull content out of nested or
16
+ * unsupported nodes.
17
+ */
18
+ export declare const getAgentMentionParentContext: (parentNode: PMNode, agentMentionLocalId?: string | null) => DocNode;
@@ -1,3 +1,4 @@
1
+ import type { DocNode } from '@atlaskit/adf-schema';
1
2
  import type { AnalyticsEventPayload } from '@atlaskit/editor-common/analytics';
2
3
  import type { Providers, ProfilecardProvider } from '@atlaskit/editor-common/provider-factory';
3
4
  import type { TypeAheadHandler } from '@atlaskit/editor-common/types';
@@ -44,7 +45,7 @@ export interface MentionsPluginOptions extends MentionPluginConfig {
44
45
  */
45
46
  export type MentionPluginOptions = MentionsPluginOptions;
46
47
  export type AgentMentionDetails = {
47
- context: string | null;
48
+ context: DocNode;
48
49
  id: string;
49
50
  localId: string;
50
51
  name: string | null;
@@ -59,6 +60,7 @@ export type AgentMentionDetails = {
59
60
  */
60
61
  parentStart: number;
61
62
  pos: number;
63
+ prompt: string | null;
62
64
  };
63
65
  export type MentionPluginState = {
64
66
  canInsertMention?: boolean;
@@ -68,10 +70,10 @@ export type MentionPluginState = {
68
70
  */
69
71
  lastAgentMentionInsertionCount?: number;
70
72
  /**
71
- * Plain-text content of the block node containing the agent mention.
73
+ * Prompt-safe ADF context from the direct parent of the agent mention.
72
74
  * Used as a prompt context for Rovo chat.
73
75
  */
74
- lastInsertedAgentMentionContext?: string | null;
76
+ lastInsertedAgentMentionContext?: DocNode | null;
75
77
  /**
76
78
  * The ID of the most recently inserted agent (APP | AGENT userType) mention.
77
79
  * Null when no agent mention is present in the document.
@@ -92,6 +94,11 @@ export type MentionPluginState = {
92
94
  * (e.g. 'taskItem', 'paragraph'). Determines auto-send vs. draft behaviour.
93
95
  */
94
96
  lastInsertedAgentMentionParentNodeType?: string | null;
97
+ /**
98
+ * Plain-text prompt from the direct parent of the agent mention.
99
+ * Preserves the pre-ADF fallback behaviour for chat input drafts.
100
+ */
101
+ lastInsertedAgentMentionPrompt?: string | null;
95
102
  mentionProvider?: MentionProvider;
96
103
  mentions?: Array<MentionDescription>;
97
104
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-mentions",
3
- "version": "14.5.8",
3
+ "version": "14.5.10",
4
4
  "description": "Mentions plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -41,7 +41,7 @@
41
41
  "@atlaskit/profilecard": "^26.5.0",
42
42
  "@atlaskit/teams-app-config": "^2.1.0",
43
43
  "@atlaskit/theme": "^26.1.0",
44
- "@atlaskit/tmp-editor-statsig": "^119.0.0",
44
+ "@atlaskit/tmp-editor-statsig": "^120.0.0",
45
45
  "@atlaskit/tokens": "^15.3.0",
46
46
  "@atlaskit/tooltip": "^23.1.0",
47
47
  "@atlaskit/user-picker": "^13.4.0",
@@ -53,7 +53,7 @@
53
53
  "uuid": "^3.1.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "@atlaskit/editor-common": "^116.19.0",
56
+ "@atlaskit/editor-common": "^116.20.0",
57
57
  "react": "^18.2.0",
58
58
  "react-dom": "^18.2.0",
59
59
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"