@atlaskit/editor-plugin-mentions 15.0.2 → 15.0.4

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.
@@ -0,0 +1,757 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ 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; } } }; }
4
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
5
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
6
+ 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; }
7
+ 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; }
8
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
9
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
10
+ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention/resource';
11
+ import { fg } from '@atlaskit/platform-feature-flags';
12
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
13
+ import { getAgentMentionParentContext } from './agent-mention-context';
14
+ import { mentionPluginKey } from './key';
15
+ import { ACTIONS } from './main';
16
+
17
+ // 'AGENT' is not in the ADF schema UserType enum but is used at runtime.
18
+
19
+ var AGENT_USER_TYPES = new Set(['APP', 'AGENT']);
20
+ var isAgentUserType = function isAgentUserType(userType) {
21
+ return typeof userType === 'string' && AGENT_USER_TYPES.has(userType);
22
+ };
23
+ var getAgentMentionName = function getAgentMentionName(text, fallbackName) {
24
+ var trimmedFallbackName = typeof fallbackName === 'string' ? fallbackName.trim() : '';
25
+ var normalizedFallbackName = (trimmedFallbackName.startsWith('@') ? trimmedFallbackName.slice(1).trim() : trimmedFallbackName) || null;
26
+ if (typeof text !== 'string') {
27
+ return normalizedFallbackName;
28
+ }
29
+ var trimmedText = text.trim();
30
+ var displayName = trimmedText.startsWith('@') ? trimmedText.slice(1).trim() : trimmedText;
31
+ var normalizedName = displayName || normalizedFallbackName;
32
+ return normalizedName;
33
+ };
34
+ var AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
35
+ var AGENT_MENTION_INACTIVITY_MS = 3000;
36
+ var MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS = 20;
37
+ /**
38
+ * Returns true when a transaction represents a local user document edit that
39
+ * should restart pending agent-mention inactivity tracking.
40
+ *
41
+ * Remote/collab updates, replace-document transactions, AI streaming transforms,
42
+ * selection-only movements, and metadata-only transactions are intentionally ignored.
43
+ */
44
+ var isQualifyingLocalUserDocChange = function isQualifyingLocalUserDocChange(tr) {
45
+ var isAIStreaming = Boolean(tr.getMeta(AI_STREAMING_TRANSFORMATION_META_KEY));
46
+ return tr.docChanged && !tr.getMeta('isRemote') && !tr.getMeta('replaceDocument') && !isAIStreaming;
47
+ };
48
+ var isLocalSelectionChange = function isLocalSelectionChange(tr, hasPositionChanged) {
49
+ var isAIStreaming = Boolean(tr.getMeta(AI_STREAMING_TRANSFORMATION_META_KEY));
50
+
51
+ // Pressing Enter can move selection through a doc split without setting tr.selectionSet
52
+ // or changing from/to numerically, so local doc changes are checked against the
53
+ // pending mention's current parent before publishing.
54
+ return (hasPositionChanged || tr.docChanged) && !tr.getMeta('isRemote') && !tr.getMeta('replaceDocument') && !isAIStreaming;
55
+ };
56
+
57
+ /**
58
+ * Reads agent-mention details from a known document position without traversing
59
+ * the document. Callers pass a matcher so mapped positions are only accepted
60
+ * when they still point at the same pending/tracked mention.
61
+ */
62
+ var getAgentMentionDetailsAtPos = function getAgentMentionDetailsAtPos(state, pos, matchesMention, fallbackName) {
63
+ var _parentNode$type$name;
64
+ if (pos < 0 || pos > state.doc.content.size) {
65
+ return null;
66
+ }
67
+ var node = state.doc.nodeAt(pos);
68
+ var mentionSchema = state.schema.nodes.mention;
69
+ if ((node === null || node === void 0 ? void 0 : node.type) !== mentionSchema || !isAgentUserType(node.attrs.userType) || !matchesMention(node.attrs) || !node.attrs.id || !node.attrs.localId) {
70
+ return null;
71
+ }
72
+ var $mentionPos = state.doc.resolve(Math.min(pos + node.nodeSize, state.doc.content.size));
73
+ var parentNode = $mentionPos.node($mentionPos.depth);
74
+ var id = node.attrs.id;
75
+ var name = getAgentMentionName(node.attrs.text, fallbackName);
76
+ return {
77
+ id: id,
78
+ localId: node.attrs.localId,
79
+ context: getAgentMentionParentContext(parentNode, node.attrs.localId),
80
+ name: name,
81
+ prompt: parentNode.textContent.trim() || null,
82
+ nodeSize: node.nodeSize,
83
+ parentEnd: $mentionPos.end($mentionPos.depth),
84
+ parentNodeType: (_parentNode$type$name = parentNode.type.name) !== null && _parentNode$type$name !== void 0 ? _parentNode$type$name : null,
85
+ parentStart: $mentionPos.start($mentionPos.depth),
86
+ pos: pos
87
+ };
88
+ };
89
+
90
+ /**
91
+ * Finds an agent mention that survived a document change when the changed-range
92
+ * scan did not find one. Uses the tracked localId as the mention instance identity
93
+ * so same-agent mentions elsewhere in the document cannot be selected as fallback.
94
+ */
95
+ var getSurvivingAgentMentionDetails = function getSurvivingAgentMentionDetails(state, preferredLocalId, preferredName) {
96
+ var mentionSchema = state.schema.nodes.mention;
97
+ var result = null;
98
+ state.doc.descendants(function (node, pos) {
99
+ if (result) {
100
+ return false;
101
+ }
102
+ if (node.type !== mentionSchema || !isAgentUserType(node.attrs.userType) || node.attrs.localId !== preferredLocalId) {
103
+ return true;
104
+ }
105
+ result = getAgentMentionDetailsAtPos(state, pos, function (attrs) {
106
+ return attrs.localId === preferredLocalId;
107
+ }, preferredName);
108
+ return !result;
109
+ });
110
+ return result;
111
+ };
112
+
113
+ /**
114
+ * Maps a pending typed agent mention through a document-changing transaction and
115
+ * returns the updated pending state. If the mapped position was deleted or no
116
+ * longer points at the same local mention, the pending mention is cleared.
117
+ */
118
+ var getPendingTypedAgentMentionAfterDocChange = function getPendingTypedAgentMentionAfterDocChange(state, tr, pendingTypedAgentMention, _ref) {
119
+ var resetTimer = _ref.resetTimer;
120
+ var mappedPos = tr.mapping.mapResult(pendingTypedAgentMention.pos, 1);
121
+ var resetCount = resetTimer ? pendingTypedAgentMention.resetCount + 1 : pendingTypedAgentMention.resetCount;
122
+ if (mappedPos.deleted) {
123
+ return null;
124
+ }
125
+ var pendingMentionDetails = getAgentMentionDetailsAtPos(state, mappedPos.pos, function (attrs) {
126
+ return attrs.localId === pendingTypedAgentMention.localId;
127
+ }, pendingTypedAgentMention.name);
128
+ return pendingMentionDetails ? {
129
+ id: pendingMentionDetails.id,
130
+ localId: pendingTypedAgentMention.localId,
131
+ name: pendingMentionDetails.name,
132
+ nodeSize: pendingMentionDetails.nodeSize,
133
+ parentNodeType: pendingMentionDetails.parentNodeType,
134
+ pos: pendingMentionDetails.pos,
135
+ resetCount: resetCount
136
+ } : null;
137
+ };
138
+ var hasPendingMentionMovedToNewParent = function hasPendingMentionMovedToNewParent(oldState, tr, previousPendingTypedAgentMention, pendingMentionDetails) {
139
+ if (!previousPendingTypedAgentMention) {
140
+ return false;
141
+ }
142
+ var previousMentionDetails = getAgentMentionDetailsAtPos(oldState, previousPendingTypedAgentMention.pos, function (attrs) {
143
+ return attrs.localId === previousPendingTypedAgentMention.localId;
144
+ });
145
+
146
+ // Keep the previous parent boundary associated with the left side of an
147
+ // insertion at that boundary, so typing at the start of the parent does not
148
+ // look like the pending mention moved into a new parent.
149
+ var mappedPreviousParentStart = previousMentionDetails && tr.mapping.map(previousMentionDetails.parentStart, -1);
150
+ return Boolean(previousMentionDetails && mappedPreviousParentStart !== pendingMentionDetails.parentStart);
151
+ };
152
+ var isSelectionOutsideDirectParent = function isSelectionOutsideDirectParent(state, pendingMentionDetails) {
153
+ return state.selection.from < pendingMentionDetails.parentStart || state.selection.to > pendingMentionDetails.parentEnd;
154
+ };
155
+
156
+ /**
157
+ * Finalises a pending typed agent mention by copying its details into the
158
+ * public lastInserted* plugin state after the caller has already resolved the
159
+ * pending mention from the current document.
160
+ */
161
+ var commitResolvedPendingTypedAgentMention = function commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails) {
162
+ var _pluginState$lastAgen;
163
+ return {
164
+ hasPublicPluginStateChanged: true,
165
+ pluginState: _objectSpread(_objectSpread({}, pluginState), {}, {
166
+ pendingTypedAgentMention: null,
167
+ lastInsertedAgentMentionId: pendingMentionDetails.id,
168
+ lastInsertedAgentMentionLocalId: pendingMentionDetails.localId,
169
+ lastInsertedAgentMentionContext: pendingMentionDetails.context,
170
+ lastInsertedAgentMentionName: pendingMentionDetails.name,
171
+ lastInsertedAgentMentionPrompt: pendingMentionDetails.prompt,
172
+ lastInsertedAgentMentionParentNodeType: pendingMentionDetails.parentNodeType,
173
+ lastAgentMentionInsertionCount: ((_pluginState$lastAgen = pluginState.lastAgentMentionInsertionCount) !== null && _pluginState$lastAgen !== void 0 ? _pluginState$lastAgen : 0) + 1
174
+ })
175
+ };
176
+ };
177
+
178
+ /**
179
+ * Resolves and finalises a pending typed agent mention. If the tracked mention
180
+ * no longer resolves, the stale pending state is cleared without dispatching a
181
+ * public update.
182
+ */
183
+ var commitPendingTypedAgentMention = function commitPendingTypedAgentMention(state, pluginState, pendingTypedAgentMention) {
184
+ var pendingMentionDetails = getAgentMentionDetailsAtPos(state, pendingTypedAgentMention.pos, function (attrs) {
185
+ return attrs.localId === pendingTypedAgentMention.localId;
186
+ }, pendingTypedAgentMention.name);
187
+ if (!pendingMentionDetails) {
188
+ return {
189
+ hasPublicPluginStateChanged: false,
190
+ pluginState: _objectSpread(_objectSpread({}, pluginState), {}, {
191
+ pendingTypedAgentMention: null
192
+ })
193
+ };
194
+ }
195
+ return commitResolvedPendingTypedAgentMention(pluginState, pendingMentionDetails);
196
+ };
197
+ var hasTrackedAgentMentionState = function hasTrackedAgentMentionState(pluginState) {
198
+ 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;
199
+ };
200
+
201
+ /**
202
+ * Clears agent mention state that points at a specific document snapshot.
203
+ * replaceDocument swaps content wholesale, so pending typed mentions and
204
+ * lastInserted* details from the previous document must be cleared together.
205
+ */
206
+ var clearTrackedAgentMentionState = function clearTrackedAgentMentionState(pluginState) {
207
+ return _objectSpread(_objectSpread(_objectSpread({}, pluginState), {}, {
208
+ pendingTypedAgentMention: null
209
+ }, fg('platform_editor_agent_mentions_drop_one_fixes') ? {
210
+ pendingPastedAgentMention: null
211
+ } : {}), {}, {
212
+ lastInsertedAgentMentionId: null,
213
+ lastInsertedAgentMentionLocalId: null,
214
+ lastInsertedAgentMentionContext: null,
215
+ lastInsertedAgentMentionName: null,
216
+ lastInsertedAgentMentionPrompt: null,
217
+ lastInsertedAgentMentionParentNodeType: null
218
+ });
219
+ };
220
+
221
+ /**
222
+ * Attempts to synchronously resolve an agent mention name from the mention
223
+ * provider's cache. Falls back to undefined if the provider doesn't support
224
+ * name resolution, the result is a Promise (async/cache miss), or the status
225
+ * is not OK.
226
+ */
227
+ var resolveCachedAgentMentionName = function resolveCachedAgentMentionName(mentionProvider, params, id) {
228
+ if (params !== null && params !== void 0 && params.name || !isResolvingMentionProvider(mentionProvider)) {
229
+ var _params$name;
230
+ return (_params$name = params === null || params === void 0 ? void 0 : params.name) !== null && _params$name !== void 0 ? _params$name : undefined;
231
+ }
232
+ var result = mentionProvider.resolveMentionName(id);
233
+ if (!(result instanceof Promise) && result.status === MentionNameStatus.OK) {
234
+ return result.name || undefined;
235
+ }
236
+ return undefined;
237
+ };
238
+
239
+ /**
240
+ * Resolves the name of a pasted agent mention via the mention provider and
241
+ * dispatches the appropriate action to update plugin state.
242
+ */
243
+ export var resolveAndDispatchPastedAgentMentionName = function resolveAndDispatchPastedAgentMentionName(agentId, mentionProvider, pendingResolveMentionIds, view) {
244
+ if (pendingResolveMentionIds.has(agentId)) {
245
+ return;
246
+ }
247
+ pendingResolveMentionIds.add(agentId);
248
+ var result = mentionProvider.resolveMentionName(agentId);
249
+ if (result instanceof Promise) {
250
+ result.then(function (nameDetails) {
251
+ pendingResolveMentionIds.delete(agentId);
252
+ if (nameDetails.status === MentionNameStatus.OK && nameDetails.name) {
253
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
254
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
255
+ params: {
256
+ id: agentId,
257
+ name: nameDetails.name
258
+ }
259
+ }));
260
+ } else {
261
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
262
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
263
+ params: {
264
+ id: agentId
265
+ }
266
+ }));
267
+ }
268
+ }).catch(function () {
269
+ pendingResolveMentionIds.delete(agentId);
270
+ });
271
+ } else if (result.status === MentionNameStatus.OK && result.name) {
272
+ pendingResolveMentionIds.delete(agentId);
273
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
274
+ action: ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME,
275
+ params: {
276
+ id: agentId,
277
+ name: result.name
278
+ }
279
+ }));
280
+ } else {
281
+ pendingResolveMentionIds.delete(agentId);
282
+ view.dispatch(view.state.tr.setMeta(mentionPluginKey, {
283
+ action: ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION,
284
+ params: {
285
+ id: agentId
286
+ }
287
+ }));
288
+ }
289
+ };
290
+ export var applyAgentMentionState = function applyAgentMentionState(_ref2) {
291
+ var tr = _ref2.tr,
292
+ pluginState = _ref2.pluginState,
293
+ oldState = _ref2.oldState,
294
+ newState = _ref2.newState,
295
+ getIsRovoPanelOpen = _ref2.getIsRovoPanelOpen;
296
+ // mentionPluginKey intentionally remains the shared transaction action channel while
297
+ // agentMentionPluginKey owns the extracted agent state.
298
+ var _ref3 = tr.getMeta(mentionPluginKey) || {
299
+ action: null,
300
+ params: null
301
+ },
302
+ action = _ref3.action,
303
+ params = _ref3.params;
304
+ var hasPublicPluginStateChanged = false;
305
+ var newPluginState = pluginState;
306
+ var isAgentMentionsExperimentEnabled = editorExperiment('platform_editor_agent_mentions', true);
307
+ var hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
308
+ switch (action) {
309
+ case ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION:
310
+ {
311
+ var pendingTypedAgentMention = newPluginState.pendingTypedAgentMention;
312
+ if (!isAgentMentionsExperimentEnabled || !pendingTypedAgentMention || pendingTypedAgentMention.localId !== (params === null || params === void 0 ? void 0 : params.localId) || pendingTypedAgentMention.resetCount !== (params === null || params === void 0 ? void 0 : params.resetCount)) {
313
+ break;
314
+ }
315
+ var commitResult = commitPendingTypedAgentMention(newState, newPluginState, pendingTypedAgentMention);
316
+ newPluginState = commitResult.pluginState;
317
+ hasPublicPluginStateChanged = hasPublicPluginStateChanged || commitResult.hasPublicPluginStateChanged;
318
+ break;
319
+ }
320
+ case ACTIONS.DISCARD_PENDING_TYPED_AGENT_MENTION:
321
+ {
322
+ var pendingTypedAgentMentionToDiscard = newPluginState.pendingTypedAgentMention;
323
+ if (!isAgentMentionsExperimentEnabled || !pendingTypedAgentMentionToDiscard || pendingTypedAgentMentionToDiscard.localId !== (params === null || params === void 0 ? void 0 : params.localId) || pendingTypedAgentMentionToDiscard.resetCount !== (params === null || params === void 0 ? void 0 : params.resetCount)) {
324
+ break;
325
+ }
326
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
327
+ pendingTypedAgentMention: null
328
+ });
329
+ hasPublicPluginStateChanged = true;
330
+ break;
331
+ }
332
+ case ACTIONS.SET_PROVIDER:
333
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
334
+ mentionProvider: params.provider
335
+ });
336
+ hasPublicPluginStateChanged = true;
337
+ break;
338
+ case ACTIONS.RESOLVE_PASTED_AGENT_MENTION_NAME:
339
+ {
340
+ var _newPluginState$pendi, _newPluginState$pendi2, _newPluginState$pendi3, _newPluginState$pendi4, _newPluginState$pendi5, _newPluginState$pendi6;
341
+ 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')) {
342
+ break;
343
+ }
344
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
345
+ pendingPastedAgentMention: null,
346
+ lastInsertedAgentMentionId: (_newPluginState$pendi2 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi2 === void 0 ? void 0 : _newPluginState$pendi2.id,
347
+ lastInsertedAgentMentionLocalId: (_newPluginState$pendi3 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi3 === void 0 ? void 0 : _newPluginState$pendi3.localId,
348
+ lastInsertedAgentMentionContext: (_newPluginState$pendi4 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi4 === void 0 ? void 0 : _newPluginState$pendi4.context,
349
+ lastInsertedAgentMentionName: params.name,
350
+ lastInsertedAgentMentionPrompt: (_newPluginState$pendi5 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi5 === void 0 ? void 0 : _newPluginState$pendi5.prompt,
351
+ lastInsertedAgentMentionParentNodeType: (_newPluginState$pendi6 = newPluginState.pendingPastedAgentMention) === null || _newPluginState$pendi6 === void 0 ? void 0 : _newPluginState$pendi6.parentNodeType
352
+ });
353
+ hasPublicPluginStateChanged = true;
354
+ break;
355
+ }
356
+ case ACTIONS.CLEAR_PENDING_PASTED_AGENT_MENTION:
357
+ {
358
+ var _newPluginState$pendi7;
359
+ 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')) {
360
+ break;
361
+ }
362
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
363
+ pendingPastedAgentMention: null
364
+ });
365
+ break;
366
+ }
367
+ }
368
+ if (isAgentMentionsExperimentEnabled && isQualifyingLocalUserDocChange(tr)) {
369
+ var mentionSchema = newState.schema.nodes.mention;
370
+ var newDocRanges = [];
371
+ var oldDocRanges = [];
372
+ var stepsTouchMentions = false;
373
+ tr.steps.forEach(function (step) {
374
+ var found = false;
375
+ var stepNewRanges = [];
376
+ var stepOldRanges = [];
377
+ step.getMap().forEach(function (oldFrom, oldTo, newFrom, newTo) {
378
+ stepOldRanges.push([oldFrom, oldTo]);
379
+ stepNewRanges.push([newFrom, newTo]);
380
+ if (!found) {
381
+ var clampedNewFrom = Math.min(newFrom, newState.doc.content.size);
382
+ var clampedNewTo = Math.min(newTo, newState.doc.content.size);
383
+ if (clampedNewFrom < clampedNewTo) {
384
+ newState.doc.nodesBetween(clampedNewFrom, clampedNewTo, function (node) {
385
+ if (node.type === mentionSchema && isAgentUserType(node.attrs.userType)) {
386
+ found = true;
387
+ }
388
+ return !found;
389
+ });
390
+ }
391
+ if (!found) {
392
+ var clampedOldFrom = Math.min(oldFrom, oldState.doc.content.size);
393
+ var clampedOldTo = Math.min(oldTo, oldState.doc.content.size);
394
+ if (clampedOldFrom < clampedOldTo) {
395
+ oldState.doc.nodesBetween(clampedOldFrom, clampedOldTo, function (node) {
396
+ if (node.type === mentionSchema && AGENT_USER_TYPES.has(node.attrs.userType)) {
397
+ found = true;
398
+ }
399
+ return !found;
400
+ });
401
+ }
402
+ }
403
+ }
404
+ });
405
+ if (found) {
406
+ stepsTouchMentions = true;
407
+ newDocRanges.push.apply(newDocRanges, stepNewRanges);
408
+ oldDocRanges.push.apply(oldDocRanges, stepOldRanges);
409
+ }
410
+ });
411
+ var shouldResolveAgentMentionState = stepsTouchMentions || Boolean(newPluginState.lastInsertedAgentMentionLocalId);
412
+ if (shouldResolveAgentMentionState) {
413
+ var _newPluginState$lastI, _newPluginState$lastA, _newPluginState$lastI2, _newPluginState$lastI3, _newPluginState$lastI4, _newPluginState$lastI5, _newPluginState$lastI6;
414
+ var agentMentionId = null;
415
+ var agentMentionLocalId = null;
416
+ var agentMentionContext = null;
417
+ var agentMentionName = null;
418
+ var agentMentionPrompt = null;
419
+ var agentMentionParentNodeType = null;
420
+ var existingAgentMentionLocalIdsInChangedRanges = new Set();
421
+ var pendingTypedAgentMentionDetails = null;
422
+ if (stepsTouchMentions) {
423
+ var _iterator = _createForOfIteratorHelper(newDocRanges),
424
+ _step;
425
+ try {
426
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
427
+ var _step$value = _slicedToArray(_step.value, 2),
428
+ from = _step$value[0],
429
+ to = _step$value[1];
430
+ var clampedTo = Math.min(to, newState.doc.content.size);
431
+ if (from >= clampedTo) {
432
+ continue;
433
+ }
434
+ newState.doc.nodesBetween(from, clampedTo, function (node, pos) {
435
+ if (node.type !== mentionSchema || !isAgentUserType(node.attrs.userType)) {
436
+ return true;
437
+ }
438
+ if (pendingTypedAgentMentionDetails === null && action === ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && node.attrs.localId === (params === null || params === void 0 ? void 0 : params.localId)) {
439
+ pendingTypedAgentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
440
+ return attrs.localId === params.localId;
441
+ }, params.name);
442
+ }
443
+ if (agentMentionLocalId === null && node.attrs.localId) {
444
+ var cachedName = fg('platform_editor_agent_mentions_drop_one_fixes') ? resolveCachedAgentMentionName(newPluginState.mentionProvider, params, node.attrs.id) : params === null || params === void 0 ? void 0 : params.name;
445
+ var agentMentionDetails = getAgentMentionDetailsAtPos(newState, pos, function (attrs) {
446
+ return attrs.localId === node.attrs.localId;
447
+ }, cachedName);
448
+ if (agentMentionDetails) {
449
+ agentMentionId = agentMentionDetails.id;
450
+ agentMentionLocalId = agentMentionDetails.localId;
451
+ agentMentionContext = agentMentionDetails.context;
452
+ agentMentionName = agentMentionDetails.name;
453
+ agentMentionPrompt = agentMentionDetails.prompt;
454
+ agentMentionParentNodeType = agentMentionDetails.parentNodeType;
455
+ }
456
+ }
457
+ return true;
458
+ });
459
+ }
460
+ } catch (err) {
461
+ _iterator.e(err);
462
+ } finally {
463
+ _iterator.f();
464
+ }
465
+ var _iterator2 = _createForOfIteratorHelper(oldDocRanges),
466
+ _step2;
467
+ try {
468
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
469
+ var _step2$value = _slicedToArray(_step2.value, 2),
470
+ _from = _step2$value[0],
471
+ _to = _step2$value[1];
472
+ var clampedOldTo = Math.min(_to, oldState.doc.content.size);
473
+ if (_from >= clampedOldTo) {
474
+ continue;
475
+ }
476
+ oldState.doc.nodesBetween(_from, clampedOldTo, function (node) {
477
+ if (node.type !== mentionSchema || !isAgentUserType(node.attrs.userType)) {
478
+ return true;
479
+ }
480
+ if (node.attrs.localId) {
481
+ existingAgentMentionLocalIdsInChangedRanges.add(node.attrs.localId);
482
+ }
483
+ return true;
484
+ });
485
+ }
486
+ } catch (err) {
487
+ _iterator2.e(err);
488
+ } finally {
489
+ _iterator2.f();
490
+ }
491
+ }
492
+ var resolvedFromFullDocFallback = false;
493
+ if (agentMentionId === null && newPluginState.lastInsertedAgentMentionLocalId) {
494
+ var survivorDetails = getSurvivingAgentMentionDetails(newState, newPluginState.lastInsertedAgentMentionLocalId, newPluginState.lastInsertedAgentMentionName);
495
+ if (survivorDetails) {
496
+ agentMentionId = survivorDetails.id;
497
+ agentMentionLocalId = survivorDetails.localId;
498
+ agentMentionContext = survivorDetails.context;
499
+ agentMentionName = survivorDetails.name;
500
+ agentMentionPrompt = survivorDetails.prompt;
501
+ agentMentionParentNodeType = survivorDetails.parentNodeType;
502
+ resolvedFromFullDocFallback = true;
503
+ }
504
+ }
505
+ var trackedAgentMentionLocalId = (_newPluginState$lastI = newPluginState.lastInsertedAgentMentionLocalId) !== null && _newPluginState$lastI !== void 0 ? _newPluginState$lastI : null;
506
+ var changedRangeMentionIsNew = agentMentionLocalId !== null && !existingAgentMentionLocalIdsInChangedRanges.has(agentMentionLocalId);
507
+ if (agentMentionLocalId !== null && !changedRangeMentionIsNew && agentMentionLocalId !== trackedAgentMentionLocalId) {
508
+ var _survivorDetails = trackedAgentMentionLocalId ? getSurvivingAgentMentionDetails(newState, trackedAgentMentionLocalId, newPluginState.lastInsertedAgentMentionName) : null;
509
+ if (_survivorDetails) {
510
+ agentMentionId = _survivorDetails.id;
511
+ agentMentionLocalId = _survivorDetails.localId;
512
+ agentMentionContext = _survivorDetails.context;
513
+ agentMentionName = _survivorDetails.name;
514
+ agentMentionParentNodeType = _survivorDetails.parentNodeType;
515
+ resolvedFromFullDocFallback = true;
516
+ } else {
517
+ agentMentionId = null;
518
+ agentMentionLocalId = null;
519
+ agentMentionContext = null;
520
+ agentMentionName = null;
521
+ agentMentionParentNodeType = null;
522
+ }
523
+ }
524
+ var isNewInsertion = agentMentionId !== null && !resolvedFromFullDocFallback && changedRangeMentionIsNew;
525
+ var isPendingTypedAgentMentionInsertion = isNewInsertion && action === ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && typeof (params === null || params === void 0 ? void 0 : params.localId) === 'string';
526
+ var newInsertionCount = isNewInsertion ? ((_newPluginState$lastA = newPluginState.lastAgentMentionInsertionCount) !== null && _newPluginState$lastA !== void 0 ? _newPluginState$lastA : 0) + 1 : undefined;
527
+ var pendingTypedAgentMentionDetailsForState = pendingTypedAgentMentionDetails;
528
+ if (isPendingTypedAgentMentionInsertion && pendingTypedAgentMentionDetailsForState) {
529
+ var pendingTypedAgentMentionLocalId = params === null || params === void 0 ? void 0 : params.localId;
530
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
531
+ pendingTypedAgentMention: {
532
+ id: pendingTypedAgentMentionDetailsForState.id,
533
+ localId: pendingTypedAgentMentionLocalId,
534
+ name: pendingTypedAgentMentionDetailsForState.name,
535
+ nodeSize: pendingTypedAgentMentionDetailsForState.nodeSize,
536
+ parentNodeType: pendingTypedAgentMentionDetailsForState.parentNodeType,
537
+ pos: pendingTypedAgentMentionDetailsForState.pos,
538
+ resetCount: 1
539
+ }
540
+ });
541
+ } else if (isPendingTypedAgentMentionInsertion) {
542
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
543
+ pendingTypedAgentMention: null,
544
+ lastInsertedAgentMentionId: agentMentionId,
545
+ lastInsertedAgentMentionLocalId: agentMentionLocalId,
546
+ lastInsertedAgentMentionContext: agentMentionContext,
547
+ lastInsertedAgentMentionName: agentMentionName,
548
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
549
+ lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
550
+ }, newInsertionCount !== undefined ? {
551
+ lastAgentMentionInsertionCount: newInsertionCount
552
+ } : {});
553
+ hasPublicPluginStateChanged = true;
554
+ } 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) {
555
+ var isTaskItemMentionForPaste = agentMentionParentNodeType === 'taskItem';
556
+ if (!isTaskItemMentionForPaste && isNewInsertion && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
557
+ // Rovo is already open, so do not publish a nudge-triggering state change.
558
+ } else if (agentMentionName === null && agentMentionId !== null && isResolvingMentionProvider(newPluginState.mentionProvider) && fg('platform_editor_agent_mentions_drop_one_fixes')) {
559
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
560
+ pendingPastedAgentMention: {
561
+ id: agentMentionId,
562
+ localId: agentMentionLocalId,
563
+ context: agentMentionContext,
564
+ prompt: agentMentionPrompt,
565
+ parentNodeType: agentMentionParentNodeType
566
+ }
567
+ }, newInsertionCount !== undefined ? {
568
+ lastAgentMentionInsertionCount: newInsertionCount
569
+ } : {});
570
+ } else {
571
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
572
+ lastInsertedAgentMentionId: agentMentionId,
573
+ lastInsertedAgentMentionLocalId: agentMentionLocalId,
574
+ lastInsertedAgentMentionContext: agentMentionContext,
575
+ lastInsertedAgentMentionName: agentMentionName,
576
+ lastInsertedAgentMentionPrompt: agentMentionPrompt,
577
+ lastInsertedAgentMentionParentNodeType: agentMentionParentNodeType
578
+ }, newInsertionCount !== undefined ? {
579
+ lastAgentMentionInsertionCount: newInsertionCount
580
+ } : {});
581
+ hasPublicPluginStateChanged = true;
582
+ }
583
+ }
584
+ }
585
+ }
586
+ if (isAgentMentionsExperimentEnabled && tr.docChanged && tr.getMeta('replaceDocument') && hasTrackedAgentMentionState(newPluginState)) {
587
+ newPluginState = clearTrackedAgentMentionState(newPluginState);
588
+ hasPublicPluginStateChanged = true;
589
+ }
590
+ if (isAgentMentionsExperimentEnabled && newPluginState.pendingTypedAgentMention && action !== ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && action !== ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION && tr.docChanged) {
591
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
592
+ pendingTypedAgentMention: getPendingTypedAgentMentionAfterDocChange(newState, tr, newPluginState.pendingTypedAgentMention, {
593
+ resetTimer: isQualifyingLocalUserDocChange(tr)
594
+ })
595
+ });
596
+ }
597
+ var shouldCheckPendingTypedAgentMentionParent = isLocalSelectionChange(tr, hasPositionChanged);
598
+ if (isAgentMentionsExperimentEnabled && newPluginState.pendingTypedAgentMention && action !== ACTIONS.SET_PENDING_TYPED_AGENT_MENTION && action !== ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION && shouldCheckPendingTypedAgentMentionParent) {
599
+ var _pendingTypedAgentMention = newPluginState.pendingTypedAgentMention;
600
+ var pendingMentionDetails = getAgentMentionDetailsAtPos(newState, _pendingTypedAgentMention.pos, function (attrs) {
601
+ return attrs.localId === _pendingTypedAgentMention.localId;
602
+ }, _pendingTypedAgentMention.name);
603
+ if (!pendingMentionDetails) {
604
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
605
+ pendingTypedAgentMention: null
606
+ });
607
+ } else if (hasPendingMentionMovedToNewParent(oldState, tr, pluginState.pendingTypedAgentMention, pendingMentionDetails) || isSelectionOutsideDirectParent(newState, pendingMentionDetails)) {
608
+ if (pendingMentionDetails.parentNodeType !== 'taskItem' && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
609
+ newPluginState = _objectSpread(_objectSpread({}, newPluginState), {}, {
610
+ pendingTypedAgentMention: null
611
+ });
612
+ hasPublicPluginStateChanged = true;
613
+ } else {
614
+ var _commitResult = commitResolvedPendingTypedAgentMention(newPluginState, pendingMentionDetails);
615
+ newPluginState = _commitResult.pluginState;
616
+ hasPublicPluginStateChanged = hasPublicPluginStateChanged || _commitResult.hasPublicPluginStateChanged;
617
+ }
618
+ }
619
+ }
620
+ return {
621
+ hasPublicPluginStateChanged: hasPublicPluginStateChanged,
622
+ pluginState: newPluginState
623
+ };
624
+ };
625
+ export var createAgentMentionPluginView = function createAgentMentionPluginView(_ref4) {
626
+ var editorView = _ref4.editorView,
627
+ getIsRovoPanelOpen = _ref4.getIsRovoPanelOpen,
628
+ stateKey = _ref4.stateKey;
629
+ var isAgentMentionsEnabled = editorExperiment('platform_editor_agent_mentions', true);
630
+ var pendingTypedAgentMentionTimer;
631
+ var pendingTypedAgentMentionTimerKey = null;
632
+ var pendingTypedAgentMentionFocusDeferCount = 0;
633
+ var pendingResolveMentionIds = new Set();
634
+ var clearPendingTypedAgentMentionTimer = function clearPendingTypedAgentMentionTimer() {
635
+ var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
636
+ _ref5$preserveFocusDe = _ref5.preserveFocusDeferCount,
637
+ preserveFocusDeferCount = _ref5$preserveFocusDe === void 0 ? false : _ref5$preserveFocusDe;
638
+ if (pendingTypedAgentMentionTimer) {
639
+ clearTimeout(pendingTypedAgentMentionTimer);
640
+ pendingTypedAgentMentionTimer = undefined;
641
+ }
642
+ pendingTypedAgentMentionTimerKey = null;
643
+ if (!preserveFocusDeferCount) {
644
+ pendingTypedAgentMentionFocusDeferCount = 0;
645
+ }
646
+ };
647
+ var shouldDeferPendingTypedAgentMention = function shouldDeferPendingTypedAgentMention() {
648
+ return typeof document !== 'undefined' && document.hasFocus() && !editorView.hasFocus();
649
+ };
650
+ var _schedulePendingTypedAgentMentionTimer = function schedulePendingTypedAgentMentionTimer(mentionPluginState) {
651
+ var _ref6 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
652
+ _ref6$preserveFocusDe = _ref6.preserveFocusDeferCount,
653
+ preserveFocusDeferCount = _ref6$preserveFocusDe === void 0 ? false : _ref6$preserveFocusDe;
654
+ if (!isAgentMentionsEnabled) {
655
+ clearPendingTypedAgentMentionTimer();
656
+ return;
657
+ }
658
+ var pendingTypedAgentMention = mentionPluginState === null || mentionPluginState === void 0 ? void 0 : mentionPluginState.pendingTypedAgentMention;
659
+ if (!pendingTypedAgentMention) {
660
+ clearPendingTypedAgentMentionTimer();
661
+ return;
662
+ }
663
+ var timerKey = "".concat(pendingTypedAgentMention.localId, ":").concat(pendingTypedAgentMention.resetCount);
664
+ if (timerKey === pendingTypedAgentMentionTimerKey) {
665
+ return;
666
+ }
667
+ clearPendingTypedAgentMentionTimer({
668
+ preserveFocusDeferCount: preserveFocusDeferCount
669
+ });
670
+ pendingTypedAgentMentionTimerKey = timerKey;
671
+ pendingTypedAgentMentionTimer = setTimeout(function () {
672
+ var _stateKey$getState;
673
+ var isTaskItemMention = pendingTypedAgentMention.parentNodeType === 'taskItem';
674
+ if (!isTaskItemMention && getIsRovoPanelOpen !== null && getIsRovoPanelOpen !== void 0 && getIsRovoPanelOpen()) {
675
+ // Agent actions continue to use mentionPluginKey as the shared transaction meta channel.
676
+ editorView.dispatch(editorView.state.tr.setMeta(mentionPluginKey, {
677
+ action: ACTIONS.DISCARD_PENDING_TYPED_AGENT_MENTION,
678
+ params: {
679
+ localId: pendingTypedAgentMention.localId,
680
+ resetCount: pendingTypedAgentMention.resetCount
681
+ }
682
+ }));
683
+ return;
684
+ }
685
+ var latestPendingTypedAgentMention = (_stateKey$getState = stateKey.getState(editorView.state)) === null || _stateKey$getState === void 0 ? void 0 : _stateKey$getState.pendingTypedAgentMention;
686
+ if (!latestPendingTypedAgentMention || latestPendingTypedAgentMention.localId !== pendingTypedAgentMention.localId || latestPendingTypedAgentMention.resetCount !== pendingTypedAgentMention.resetCount) {
687
+ return;
688
+ }
689
+ if (shouldDeferPendingTypedAgentMention() && pendingTypedAgentMentionFocusDeferCount < MAX_PENDING_TYPED_AGENT_MENTION_FOCUS_DEFERS) {
690
+ pendingTypedAgentMentionFocusDeferCount++;
691
+ pendingTypedAgentMentionTimerKey = null;
692
+ _schedulePendingTypedAgentMentionTimer(stateKey.getState(editorView.state), {
693
+ preserveFocusDeferCount: true
694
+ });
695
+ return;
696
+ }
697
+ pendingTypedAgentMentionFocusDeferCount = 0;
698
+ editorView.dispatch(editorView.state.tr.setMeta(mentionPluginKey, {
699
+ action: ACTIONS.COMMIT_PENDING_TYPED_AGENT_MENTION,
700
+ params: {
701
+ localId: pendingTypedAgentMention.localId,
702
+ resetCount: pendingTypedAgentMention.resetCount
703
+ }
704
+ }));
705
+ }, AGENT_MENTION_INACTIVITY_MS);
706
+ };
707
+ return {
708
+ update: function update(view, prevState) {
709
+ var _mentionPluginState$p;
710
+ var mentionPluginState = stateKey.getState(view.state);
711
+ if (mentionPluginState === stateKey.getState(prevState)) {
712
+ return;
713
+ }
714
+ _schedulePendingTypedAgentMentionTimer(mentionPluginState);
715
+ 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')) {
716
+ resolveAndDispatchPastedAgentMentionName(mentionPluginState.pendingPastedAgentMention.id, mentionPluginState.mentionProvider, pendingResolveMentionIds, view);
717
+ }
718
+ },
719
+ destroy: function destroy() {
720
+ clearPendingTypedAgentMentionTimer();
721
+ }
722
+ };
723
+ };
724
+ export var agentMentionPluginKey = new PluginKey('agentMention');
725
+ export var createAgentMentionPlugin = function createAgentMentionPlugin(_ref7) {
726
+ var options = _ref7.options,
727
+ pmPluginFactoryParams = _ref7.pmPluginFactoryParams;
728
+ return new SafePlugin({
729
+ key: agentMentionPluginKey,
730
+ state: {
731
+ init: function init() {
732
+ return {};
733
+ },
734
+ apply: function apply(tr, pluginState, oldState, newState) {
735
+ var result = applyAgentMentionState({
736
+ tr: tr,
737
+ pluginState: pluginState,
738
+ oldState: oldState,
739
+ newState: newState,
740
+ getIsRovoPanelOpen: options === null || options === void 0 ? void 0 : options.getIsRovoPanelOpen
741
+ });
742
+ var mentionPluginState = mentionPluginKey.getState(newState);
743
+ if (result.hasPublicPluginStateChanged) {
744
+ pmPluginFactoryParams.dispatch(mentionPluginKey, _objectSpread(_objectSpread({}, mentionPluginState), result.pluginState));
745
+ }
746
+ return result.pluginState;
747
+ }
748
+ },
749
+ view: function view(editorView) {
750
+ return createAgentMentionPluginView({
751
+ editorView: editorView,
752
+ getIsRovoPanelOpen: options === null || options === void 0 ? void 0 : options.getIsRovoPanelOpen,
753
+ stateKey: agentMentionPluginKey
754
+ });
755
+ }
756
+ });
757
+ };