@atlaskit/editor-plugin-collab-edit 13.3.1 → 13.4.1
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 +24 -0
- package/dist/cjs/pm-plugins/actions.js +17 -0
- package/dist/cjs/pm-plugins/main/agent-review-segments.js +178 -0
- package/dist/es2019/pm-plugins/actions.js +17 -0
- package/dist/es2019/pm-plugins/main/agent-review-segments.js +165 -0
- package/dist/esm/pm-plugins/actions.js +17 -0
- package/dist/esm/pm-plugins/main/agent-review-segments.js +173 -0
- package/dist/types/pm-plugins/main/agent-review-segments.d.ts +16 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-collab-edit
|
|
2
2
|
|
|
3
|
+
## 13.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 13.4.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`95e5e100318c4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/95e5e100318c4) -
|
|
14
|
+
Review moment (Post Stream Review) for BE streaming — record remote agent edits into
|
|
15
|
+
aiContentPositions and open/append the Review moment (hybrid completion signal + idle debounce).
|
|
16
|
+
- New `@atlaskit/editor-common/collab/agent-remote-edit-review` subpath export for the neutral
|
|
17
|
+
agent-edit review contract (AGENT_REMOTE_EDIT_REVIEW_DATA, AgentRemoteEditReviewSegment,
|
|
18
|
+
AgentRemoteEditReviewData).
|
|
19
|
+
- Fix chimera delete diffs in agent-review-segments: per-step backward StepMap mapping replaces
|
|
20
|
+
the previous group-then-invert approach that produced blended original text when multiple
|
|
21
|
+
discrete operations (delete + insert) interacted in the same region.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
|
|
3
27
|
## 13.3.1
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -7,12 +7,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.registerAllCustomSteps = exports.handleTelePointer = exports.handlePresence = exports.handleInit = exports.handleConnection = exports.getSendableSelection = exports.applyRemoteSteps = exports.applyRemoteData = void 0;
|
|
8
8
|
var allAdfSchemaSteps = _interopRequireWildcard(require("@atlaskit/adf-schema/steps"));
|
|
9
9
|
var allAtlaskitCustomSteps = _interopRequireWildcard(require("@atlaskit/custom-steps"));
|
|
10
|
+
var _collabAgentRemoteEditReview = require("@atlaskit/editor-common/collab-agent-remote-edit-review");
|
|
10
11
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
11
12
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
12
13
|
var _prosemirrorCollab = require("@atlaskit/prosemirror-collab");
|
|
13
14
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
14
15
|
var _expVal = require("@atlaskit/tmp-editor-statsig/expVal");
|
|
15
16
|
var _analytics = require("./analytics");
|
|
17
|
+
var _agentReviewSegments = require("./main/agent-review-segments");
|
|
16
18
|
var _agentShimmerDecorations = require("./main/agent-shimmer-decorations");
|
|
17
19
|
var _agentShimmerRanges = require("./main/agent-shimmer-ranges");
|
|
18
20
|
var _utils = require("./utils");
|
|
@@ -112,6 +114,21 @@ var applyRemoteSteps = exports.applyRemoteSteps = function applyRemoteSteps(json
|
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
|
|
117
|
+
// [CCI-17994] Post Stream Review ("Review moment") for BE streaming. Record what
|
|
118
|
+
// the agent just wrote (original + new slice per contiguous change) onto this same
|
|
119
|
+
// transaction. `editor-plugin-ai` consumes this neutral meta to populate
|
|
120
|
+
// `aiContentPositions` and — only on the requester's client — open the Review
|
|
121
|
+
// moment once the edit settles. Gated on `platform_editor_agent_be_streaming`
|
|
122
|
+
// alongside shimmer; `getAgentEditSegments` also self-gates by returning null
|
|
123
|
+
// unless the batch contains agent-authored steps (and never throws), so this is
|
|
124
|
+
// a no-op for ordinary collaborator edits and can't affect step application.
|
|
125
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_agent_be_streaming', 'isEnabled', true)) {
|
|
126
|
+
var reviewData = (0, _agentReviewSegments.getAgentEditSegments)(json, steps, tr, view);
|
|
127
|
+
if (reviewData) {
|
|
128
|
+
tr.setMeta(_collabAgentRemoteEditReview.AGENT_REMOTE_EDIT_REVIEW_DATA, reviewData);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
115
132
|
/*
|
|
116
133
|
* Persist marks across transactions. Fixes an issue where
|
|
117
134
|
* marks are lost if remote transactions are dispatched
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getAgentEditSegments = void 0;
|
|
7
|
+
var _prosemirrorCollab = require("@atlaskit/prosemirror-collab");
|
|
8
|
+
var _agentShimmerRanges = require("./agent-shimmer-ranges");
|
|
9
|
+
// [CCI-17994] Post Stream Review ("Review moment") recording for BE streaming.
|
|
10
|
+
//
|
|
11
|
+
// Sibling to `getAgentShimmerRanges`: same idea of deriving what the agent wrote
|
|
12
|
+
// from a received remote-step batch, but for a DIFFERENT consumer. The shimmer
|
|
13
|
+
// only needs the NEW extent of added content (to draw a skeleton), so it drops
|
|
14
|
+
// pure deletions and expands to whole blocks. The Review moment instead needs, per
|
|
15
|
+
// contiguous change, BOTH the original slice (pre-edit, for undo / "compare with
|
|
16
|
+
// original") and the new slice (for redo), AND it must keep deletions (a removed
|
|
17
|
+
// paragraph is a reviewable change). So this derives the actual changed extents
|
|
18
|
+
// and reconstructs the pre-edit slice from `tr.before`.
|
|
19
|
+
//
|
|
20
|
+
// The output is a neutral `AgentRemoteEditReviewData` (contract in editor-common);
|
|
21
|
+
// `editor-plugin-ai`'s session-context plugin turns each segment into a coarse
|
|
22
|
+
// `aiContentPositions` entry, reusing the entire FE Review moment pipeline.
|
|
23
|
+
|
|
24
|
+
var clampToDoc = function clampToDoc(doc, pos) {
|
|
25
|
+
return Math.min(Math.max(pos, 0), doc.content.size);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Map a position in doc_{i+1} forward through the remaining steps to final-doc
|
|
29
|
+
// coords. Mirrors the shimmer's `mapToFinalDoc` — a later step's own inserted
|
|
30
|
+
// content starts at its `from`; only subsequent steps shift it.
|
|
31
|
+
var mapToFinalDoc = function mapToFinalDoc(steps, pos, stepIndex, bias) {
|
|
32
|
+
var p = pos;
|
|
33
|
+
for (var j = stepIndex + 1; j < steps.length; j++) {
|
|
34
|
+
p = steps[j].getMap().map(p, bias);
|
|
35
|
+
}
|
|
36
|
+
return p;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Derive per-change Review moment segments from an agent-authored remote-step
|
|
41
|
+
* batch. Returns `null` when there is nothing to record (no agent steps, or a
|
|
42
|
+
* rebase invalidated our index math, or derivation threw) so the caller can no-op
|
|
43
|
+
* safely — this must never throw into the shared remote-step handler.
|
|
44
|
+
*
|
|
45
|
+
* @param json the raw received step JSON (carries `agentType` / `agentId` / `userId`)
|
|
46
|
+
* @param steps the parsed PM steps (index-aligned with `json`)
|
|
47
|
+
* @param tr the transaction that applied `steps` (so `tr.before`/`tr.doc`/`tr.mapping` are available)
|
|
48
|
+
* @param view the editor view (for the collab rebase guard)
|
|
49
|
+
*/
|
|
50
|
+
var getAgentEditSegments = exports.getAgentEditSegments = function getAgentEditSegments(json, steps, tr, view) {
|
|
51
|
+
// `agentType` present ⇒ agent-authored (per the NCS↔Editor steps contract). Read
|
|
52
|
+
// from the first agent step; it is identical across a batch.
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
var agentStep = json.find(function (step) {
|
|
55
|
+
return typeof (step === null || step === void 0 ? void 0 : step.agentType) === 'string';
|
|
56
|
+
});
|
|
57
|
+
var agentType = agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentType;
|
|
58
|
+
if (agentType === undefined) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
// The user the agent acted on behalf of (the requester). Optional/additive on the
|
|
62
|
+
// step contract, so it may be absent.
|
|
63
|
+
var actorUserId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.userId) === 'string' ? agentStep.userId : undefined;
|
|
64
|
+
// Which agent instance wrote the batch. Additive on the step contract like
|
|
65
|
+
// `userId`, so treat it as optional. Carried for contract clarity / future
|
|
66
|
+
// per-agent attribution; nothing consumes it yet.
|
|
67
|
+
var agentId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentId) === 'string' ? agentStep.agentId : undefined;
|
|
68
|
+
// Hybrid end-of-edit seam: if the BE/NCS flags a batch as the terminal one, carry
|
|
69
|
+
// it so the AI plugin can open review immediately instead of waiting for the
|
|
70
|
+
// debounce. Additive marker; absent for streaming (non-final) batches.
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
var complete = json.some(function (step) {
|
|
73
|
+
return (step === null || step === void 0 ? void 0 : step.agentEditComplete) === true;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Same rebase guard as the shimmer: index-based range math is only valid if any
|
|
77
|
+
// rebased-over local steps shifted no positions. Degrade to no recording otherwise.
|
|
78
|
+
if (Number(tr.getMeta('rebased')) > 0) {
|
|
79
|
+
var _getCollabState$uncon, _getCollabState;
|
|
80
|
+
var unconfirmed = (_getCollabState$uncon = (_getCollabState = (0, _prosemirrorCollab.getCollabState)(view.state)) === null || _getCollabState === void 0 ? void 0 : _getCollabState.unconfirmed) !== null && _getCollabState$uncon !== void 0 ? _getCollabState$uncon : [];
|
|
81
|
+
if (unconfirmed.some(function (entry) {
|
|
82
|
+
return !(0, _agentShimmerRanges.isPositionNeutralStep)(entry.step);
|
|
83
|
+
})) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
// Compute one segment per step-level StepMap range. Each agent step's changed
|
|
89
|
+
// extent is taken from its StepMap (the canonical, step-type-agnostic source).
|
|
90
|
+
// Unlike the shimmer we KEEP zero-width new extents — a pure deletion has
|
|
91
|
+
// `newEnd === newStart` but is a reviewable `remove`.
|
|
92
|
+
//
|
|
93
|
+
// We derive the originalSlice/newSlice PER RANGE (per step) rather than
|
|
94
|
+
// grouping ranges first and then inverting over a merged range. Grouping
|
|
95
|
+
// before slicing corrupts the invert-mapping: when multiple discrete
|
|
96
|
+
// operations (e.g. two deleteNode + one insertNodeAfter) are merged into one
|
|
97
|
+
// range, mapping that merged range back through the inverted mapping produces
|
|
98
|
+
// a chimera — a blend of old and new text that never existed in the document.
|
|
99
|
+
//
|
|
100
|
+
// The downstream PSR pipeline (mergeOverlappingSegments +
|
|
101
|
+
// calculateTopLevelNodeSegments) already handles overlapping/adjacent coarse
|
|
102
|
+
// entries correctly, so grouping here is unnecessary.
|
|
103
|
+
|
|
104
|
+
var segments = [];
|
|
105
|
+
json.forEach(function (rawStep, index) {
|
|
106
|
+
if (typeof (rawStep === null || rawStep === void 0 ? void 0 : rawStep.agentType) !== 'string') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
|
+
var pmStep = steps[index];
|
|
111
|
+
if (typeof (pmStep === null || pmStep === void 0 ? void 0 : pmStep.getMap) !== 'function') {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
pmStep.getMap().forEach(function (oldStart, oldEnd, newStart, newEnd) {
|
|
115
|
+
try {
|
|
116
|
+
// NEW-doc coordinates: map this step's newStart/newEnd forward
|
|
117
|
+
// through all subsequent steps to get final-doc positions.
|
|
118
|
+
var finalFrom = mapToFinalDoc(steps, newStart, index, -1);
|
|
119
|
+
var finalTo = mapToFinalDoc(steps, newEnd, index, 1);
|
|
120
|
+
var newFrom = clampToDoc(tr.doc, Math.min(finalFrom, finalTo));
|
|
121
|
+
var newTo = clampToDoc(tr.doc, Math.max(finalFrom, finalTo));
|
|
122
|
+
|
|
123
|
+
// ORIGINAL-doc coordinates: map this step's oldStart/oldEnd
|
|
124
|
+
// BACKWARD through all preceding steps to get pre-batch
|
|
125
|
+
// (`tr.before`) positions. Each preceding step's StepMap tells
|
|
126
|
+
// us how positions shifted; we invert that shift by mapping
|
|
127
|
+
// through the inverted StepMap.
|
|
128
|
+
//
|
|
129
|
+
// This is the key difference from using `tr.mapping.invert()`
|
|
130
|
+
// which inverts ALL steps at once — that produces chimera text
|
|
131
|
+
// when multiple discrete operations (delete + delete + insert)
|
|
132
|
+
// interact in the same region. Per-step backward mapping keeps
|
|
133
|
+
// each operation's original range isolated.
|
|
134
|
+
var origStart = oldStart;
|
|
135
|
+
var origEnd = oldEnd;
|
|
136
|
+
for (var j = index - 1; j >= 0; j--) {
|
|
137
|
+
var prevMap = steps[j].getMap().invert();
|
|
138
|
+
origStart = prevMap.map(origStart, -1);
|
|
139
|
+
origEnd = prevMap.map(origEnd, 1);
|
|
140
|
+
}
|
|
141
|
+
var origFrom = clampToDoc(tr.before, Math.min(origStart, origEnd));
|
|
142
|
+
var origTo = clampToDoc(tr.before, Math.max(origStart, origEnd));
|
|
143
|
+
var originalSlice = tr.before.slice(origFrom, origTo);
|
|
144
|
+
var newSlice = tr.doc.slice(newFrom, newTo);
|
|
145
|
+
var originalEmpty = originalSlice.content.size === 0;
|
|
146
|
+
var newEmpty = newSlice.content.size === 0;
|
|
147
|
+
// A truly empty-to-empty region is not a change — skip it.
|
|
148
|
+
if (originalEmpty && newEmpty) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
var kind = originalEmpty ? 'add' : newEmpty ? 'remove' : 'update';
|
|
152
|
+
segments.push({
|
|
153
|
+
startPos: newFrom,
|
|
154
|
+
endPos: newTo,
|
|
155
|
+
originalSlice: originalSlice,
|
|
156
|
+
newSlice: newSlice,
|
|
157
|
+
kind: kind
|
|
158
|
+
});
|
|
159
|
+
} catch (_unused) {
|
|
160
|
+
// One bad range must not drop the others.
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
if (!segments.length) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
actorUserId: actorUserId,
|
|
169
|
+
agentId: agentId,
|
|
170
|
+
agentType: agentType,
|
|
171
|
+
complete: complete,
|
|
172
|
+
segments: segments
|
|
173
|
+
};
|
|
174
|
+
} catch (_unused2) {
|
|
175
|
+
// Never throw into the shared remote-step handler; degrade to no recording.
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
@@ -4,12 +4,14 @@ import * as allAdfSchemaSteps from '@atlaskit/adf-schema/steps';
|
|
|
4
4
|
// Ignored via go/ees005
|
|
5
5
|
// eslint-disable-next-line import/no-namespace
|
|
6
6
|
import * as allAtlaskitCustomSteps from '@atlaskit/custom-steps';
|
|
7
|
+
import { AGENT_REMOTE_EDIT_REVIEW_DATA } from '@atlaskit/editor-common/collab-agent-remote-edit-review';
|
|
7
8
|
import { AllSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
9
|
import { Step } from '@atlaskit/editor-prosemirror/transform';
|
|
9
10
|
import { receiveTransaction } from '@atlaskit/prosemirror-collab';
|
|
10
11
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
12
|
import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
|
|
12
13
|
import { getAgentEditShimmerNotShownPayload } from './analytics';
|
|
14
|
+
import { getAgentEditSegments } from './main/agent-review-segments';
|
|
13
15
|
import { ADD_AGENT_SHIMMER_META, AGENT_EDIT_HIGHLIGHT_DEFAULT_DURATION_MS, AGENT_SHIMMER_DEFAULT_DURATION_MS, HIGHLIGHT_AGENT_SHIMMER_META, REMOVE_AGENT_SHIMMER_META } from './main/agent-shimmer-decorations';
|
|
14
16
|
import { getAgentShimmerRanges } from './main/agent-shimmer-ranges';
|
|
15
17
|
import { replaceDocument } from './utils';
|
|
@@ -114,6 +116,21 @@ export const applyRemoteSteps = (json, view, userIds, options, editorAnalyticsAp
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
// [CCI-17994] Post Stream Review ("Review moment") for BE streaming. Record what
|
|
120
|
+
// the agent just wrote (original + new slice per contiguous change) onto this same
|
|
121
|
+
// transaction. `editor-plugin-ai` consumes this neutral meta to populate
|
|
122
|
+
// `aiContentPositions` and — only on the requester's client — open the Review
|
|
123
|
+
// moment once the edit settles. Gated on `platform_editor_agent_be_streaming`
|
|
124
|
+
// alongside shimmer; `getAgentEditSegments` also self-gates by returning null
|
|
125
|
+
// unless the batch contains agent-authored steps (and never throws), so this is
|
|
126
|
+
// a no-op for ordinary collaborator edits and can't affect step application.
|
|
127
|
+
if (expValEquals('platform_editor_agent_be_streaming', 'isEnabled', true)) {
|
|
128
|
+
const reviewData = getAgentEditSegments(json, steps, tr, view);
|
|
129
|
+
if (reviewData) {
|
|
130
|
+
tr.setMeta(AGENT_REMOTE_EDIT_REVIEW_DATA, reviewData);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
117
134
|
/*
|
|
118
135
|
* Persist marks across transactions. Fixes an issue where
|
|
119
136
|
* marks are lost if remote transactions are dispatched
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { getCollabState } from '@atlaskit/prosemirror-collab';
|
|
2
|
+
import { isPositionNeutralStep } from './agent-shimmer-ranges';
|
|
3
|
+
|
|
4
|
+
// [CCI-17994] Post Stream Review ("Review moment") recording for BE streaming.
|
|
5
|
+
//
|
|
6
|
+
// Sibling to `getAgentShimmerRanges`: same idea of deriving what the agent wrote
|
|
7
|
+
// from a received remote-step batch, but for a DIFFERENT consumer. The shimmer
|
|
8
|
+
// only needs the NEW extent of added content (to draw a skeleton), so it drops
|
|
9
|
+
// pure deletions and expands to whole blocks. The Review moment instead needs, per
|
|
10
|
+
// contiguous change, BOTH the original slice (pre-edit, for undo / "compare with
|
|
11
|
+
// original") and the new slice (for redo), AND it must keep deletions (a removed
|
|
12
|
+
// paragraph is a reviewable change). So this derives the actual changed extents
|
|
13
|
+
// and reconstructs the pre-edit slice from `tr.before`.
|
|
14
|
+
//
|
|
15
|
+
// The output is a neutral `AgentRemoteEditReviewData` (contract in editor-common);
|
|
16
|
+
// `editor-plugin-ai`'s session-context plugin turns each segment into a coarse
|
|
17
|
+
// `aiContentPositions` entry, reusing the entire FE Review moment pipeline.
|
|
18
|
+
|
|
19
|
+
const clampToDoc = (doc, pos) => Math.min(Math.max(pos, 0), doc.content.size);
|
|
20
|
+
|
|
21
|
+
// Map a position in doc_{i+1} forward through the remaining steps to final-doc
|
|
22
|
+
// coords. Mirrors the shimmer's `mapToFinalDoc` — a later step's own inserted
|
|
23
|
+
// content starts at its `from`; only subsequent steps shift it.
|
|
24
|
+
const mapToFinalDoc = (steps, pos, stepIndex, bias) => {
|
|
25
|
+
let p = pos;
|
|
26
|
+
for (let j = stepIndex + 1; j < steps.length; j++) {
|
|
27
|
+
p = steps[j].getMap().map(p, bias);
|
|
28
|
+
}
|
|
29
|
+
return p;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Derive per-change Review moment segments from an agent-authored remote-step
|
|
34
|
+
* batch. Returns `null` when there is nothing to record (no agent steps, or a
|
|
35
|
+
* rebase invalidated our index math, or derivation threw) so the caller can no-op
|
|
36
|
+
* safely — this must never throw into the shared remote-step handler.
|
|
37
|
+
*
|
|
38
|
+
* @param json the raw received step JSON (carries `agentType` / `agentId` / `userId`)
|
|
39
|
+
* @param steps the parsed PM steps (index-aligned with `json`)
|
|
40
|
+
* @param tr the transaction that applied `steps` (so `tr.before`/`tr.doc`/`tr.mapping` are available)
|
|
41
|
+
* @param view the editor view (for the collab rebase guard)
|
|
42
|
+
*/
|
|
43
|
+
export const getAgentEditSegments = (json, steps, tr, view) => {
|
|
44
|
+
// `agentType` present ⇒ agent-authored (per the NCS↔Editor steps contract). Read
|
|
45
|
+
// from the first agent step; it is identical across a batch.
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
const agentStep = json.find(step => typeof (step === null || step === void 0 ? void 0 : step.agentType) === 'string');
|
|
48
|
+
const agentType = agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentType;
|
|
49
|
+
if (agentType === undefined) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// The user the agent acted on behalf of (the requester). Optional/additive on the
|
|
53
|
+
// step contract, so it may be absent.
|
|
54
|
+
const actorUserId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.userId) === 'string' ? agentStep.userId : undefined;
|
|
55
|
+
// Which agent instance wrote the batch. Additive on the step contract like
|
|
56
|
+
// `userId`, so treat it as optional. Carried for contract clarity / future
|
|
57
|
+
// per-agent attribution; nothing consumes it yet.
|
|
58
|
+
const agentId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentId) === 'string' ? agentStep.agentId : undefined;
|
|
59
|
+
// Hybrid end-of-edit seam: if the BE/NCS flags a batch as the terminal one, carry
|
|
60
|
+
// it so the AI plugin can open review immediately instead of waiting for the
|
|
61
|
+
// debounce. Additive marker; absent for streaming (non-final) batches.
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
const complete = json.some(step => (step === null || step === void 0 ? void 0 : step.agentEditComplete) === true);
|
|
64
|
+
|
|
65
|
+
// Same rebase guard as the shimmer: index-based range math is only valid if any
|
|
66
|
+
// rebased-over local steps shifted no positions. Degrade to no recording otherwise.
|
|
67
|
+
if (Number(tr.getMeta('rebased')) > 0) {
|
|
68
|
+
var _getCollabState$uncon, _getCollabState;
|
|
69
|
+
const unconfirmed = (_getCollabState$uncon = (_getCollabState = getCollabState(view.state)) === null || _getCollabState === void 0 ? void 0 : _getCollabState.unconfirmed) !== null && _getCollabState$uncon !== void 0 ? _getCollabState$uncon : [];
|
|
70
|
+
if (unconfirmed.some(entry => !isPositionNeutralStep(entry.step))) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
// Compute one segment per step-level StepMap range. Each agent step's changed
|
|
76
|
+
// extent is taken from its StepMap (the canonical, step-type-agnostic source).
|
|
77
|
+
// Unlike the shimmer we KEEP zero-width new extents — a pure deletion has
|
|
78
|
+
// `newEnd === newStart` but is a reviewable `remove`.
|
|
79
|
+
//
|
|
80
|
+
// We derive the originalSlice/newSlice PER RANGE (per step) rather than
|
|
81
|
+
// grouping ranges first and then inverting over a merged range. Grouping
|
|
82
|
+
// before slicing corrupts the invert-mapping: when multiple discrete
|
|
83
|
+
// operations (e.g. two deleteNode + one insertNodeAfter) are merged into one
|
|
84
|
+
// range, mapping that merged range back through the inverted mapping produces
|
|
85
|
+
// a chimera — a blend of old and new text that never existed in the document.
|
|
86
|
+
//
|
|
87
|
+
// The downstream PSR pipeline (mergeOverlappingSegments +
|
|
88
|
+
// calculateTopLevelNodeSegments) already handles overlapping/adjacent coarse
|
|
89
|
+
// entries correctly, so grouping here is unnecessary.
|
|
90
|
+
|
|
91
|
+
const segments = [];
|
|
92
|
+
json.forEach((rawStep, index) => {
|
|
93
|
+
if (typeof (rawStep === null || rawStep === void 0 ? void 0 : rawStep.agentType) !== 'string') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
97
|
+
const pmStep = steps[index];
|
|
98
|
+
if (typeof (pmStep === null || pmStep === void 0 ? void 0 : pmStep.getMap) !== 'function') {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
pmStep.getMap().forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
102
|
+
try {
|
|
103
|
+
// NEW-doc coordinates: map this step's newStart/newEnd forward
|
|
104
|
+
// through all subsequent steps to get final-doc positions.
|
|
105
|
+
const finalFrom = mapToFinalDoc(steps, newStart, index, -1);
|
|
106
|
+
const finalTo = mapToFinalDoc(steps, newEnd, index, 1);
|
|
107
|
+
const newFrom = clampToDoc(tr.doc, Math.min(finalFrom, finalTo));
|
|
108
|
+
const newTo = clampToDoc(tr.doc, Math.max(finalFrom, finalTo));
|
|
109
|
+
|
|
110
|
+
// ORIGINAL-doc coordinates: map this step's oldStart/oldEnd
|
|
111
|
+
// BACKWARD through all preceding steps to get pre-batch
|
|
112
|
+
// (`tr.before`) positions. Each preceding step's StepMap tells
|
|
113
|
+
// us how positions shifted; we invert that shift by mapping
|
|
114
|
+
// through the inverted StepMap.
|
|
115
|
+
//
|
|
116
|
+
// This is the key difference from using `tr.mapping.invert()`
|
|
117
|
+
// which inverts ALL steps at once — that produces chimera text
|
|
118
|
+
// when multiple discrete operations (delete + delete + insert)
|
|
119
|
+
// interact in the same region. Per-step backward mapping keeps
|
|
120
|
+
// each operation's original range isolated.
|
|
121
|
+
let origStart = oldStart;
|
|
122
|
+
let origEnd = oldEnd;
|
|
123
|
+
for (let j = index - 1; j >= 0; j--) {
|
|
124
|
+
const prevMap = steps[j].getMap().invert();
|
|
125
|
+
origStart = prevMap.map(origStart, -1);
|
|
126
|
+
origEnd = prevMap.map(origEnd, 1);
|
|
127
|
+
}
|
|
128
|
+
const origFrom = clampToDoc(tr.before, Math.min(origStart, origEnd));
|
|
129
|
+
const origTo = clampToDoc(tr.before, Math.max(origStart, origEnd));
|
|
130
|
+
const originalSlice = tr.before.slice(origFrom, origTo);
|
|
131
|
+
const newSlice = tr.doc.slice(newFrom, newTo);
|
|
132
|
+
const originalEmpty = originalSlice.content.size === 0;
|
|
133
|
+
const newEmpty = newSlice.content.size === 0;
|
|
134
|
+
// A truly empty-to-empty region is not a change — skip it.
|
|
135
|
+
if (originalEmpty && newEmpty) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const kind = originalEmpty ? 'add' : newEmpty ? 'remove' : 'update';
|
|
139
|
+
segments.push({
|
|
140
|
+
startPos: newFrom,
|
|
141
|
+
endPos: newTo,
|
|
142
|
+
originalSlice,
|
|
143
|
+
newSlice,
|
|
144
|
+
kind
|
|
145
|
+
});
|
|
146
|
+
} catch {
|
|
147
|
+
// One bad range must not drop the others.
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
if (!segments.length) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
actorUserId,
|
|
156
|
+
agentId,
|
|
157
|
+
agentType,
|
|
158
|
+
complete,
|
|
159
|
+
segments
|
|
160
|
+
};
|
|
161
|
+
} catch {
|
|
162
|
+
// Never throw into the shared remote-step handler; degrade to no recording.
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
@@ -4,12 +4,14 @@ import * as allAdfSchemaSteps from '@atlaskit/adf-schema/steps';
|
|
|
4
4
|
// Ignored via go/ees005
|
|
5
5
|
// eslint-disable-next-line import/no-namespace
|
|
6
6
|
import * as allAtlaskitCustomSteps from '@atlaskit/custom-steps';
|
|
7
|
+
import { AGENT_REMOTE_EDIT_REVIEW_DATA } from '@atlaskit/editor-common/collab-agent-remote-edit-review';
|
|
7
8
|
import { AllSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
9
|
import { Step } from '@atlaskit/editor-prosemirror/transform';
|
|
9
10
|
import { receiveTransaction } from '@atlaskit/prosemirror-collab';
|
|
10
11
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
12
|
import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
|
|
12
13
|
import { getAgentEditShimmerNotShownPayload } from './analytics';
|
|
14
|
+
import { getAgentEditSegments } from './main/agent-review-segments';
|
|
13
15
|
import { ADD_AGENT_SHIMMER_META, AGENT_EDIT_HIGHLIGHT_DEFAULT_DURATION_MS, AGENT_SHIMMER_DEFAULT_DURATION_MS, HIGHLIGHT_AGENT_SHIMMER_META, REMOVE_AGENT_SHIMMER_META } from './main/agent-shimmer-decorations';
|
|
14
16
|
import { getAgentShimmerRanges } from './main/agent-shimmer-ranges';
|
|
15
17
|
import { replaceDocument } from './utils';
|
|
@@ -103,6 +105,21 @@ export var applyRemoteSteps = function applyRemoteSteps(json, view, userIds, opt
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
// [CCI-17994] Post Stream Review ("Review moment") for BE streaming. Record what
|
|
109
|
+
// the agent just wrote (original + new slice per contiguous change) onto this same
|
|
110
|
+
// transaction. `editor-plugin-ai` consumes this neutral meta to populate
|
|
111
|
+
// `aiContentPositions` and — only on the requester's client — open the Review
|
|
112
|
+
// moment once the edit settles. Gated on `platform_editor_agent_be_streaming`
|
|
113
|
+
// alongside shimmer; `getAgentEditSegments` also self-gates by returning null
|
|
114
|
+
// unless the batch contains agent-authored steps (and never throws), so this is
|
|
115
|
+
// a no-op for ordinary collaborator edits and can't affect step application.
|
|
116
|
+
if (expValEquals('platform_editor_agent_be_streaming', 'isEnabled', true)) {
|
|
117
|
+
var reviewData = getAgentEditSegments(json, steps, tr, view);
|
|
118
|
+
if (reviewData) {
|
|
119
|
+
tr.setMeta(AGENT_REMOTE_EDIT_REVIEW_DATA, reviewData);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
106
123
|
/*
|
|
107
124
|
* Persist marks across transactions. Fixes an issue where
|
|
108
125
|
* marks are lost if remote transactions are dispatched
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { getCollabState } from '@atlaskit/prosemirror-collab';
|
|
2
|
+
import { isPositionNeutralStep } from './agent-shimmer-ranges';
|
|
3
|
+
|
|
4
|
+
// [CCI-17994] Post Stream Review ("Review moment") recording for BE streaming.
|
|
5
|
+
//
|
|
6
|
+
// Sibling to `getAgentShimmerRanges`: same idea of deriving what the agent wrote
|
|
7
|
+
// from a received remote-step batch, but for a DIFFERENT consumer. The shimmer
|
|
8
|
+
// only needs the NEW extent of added content (to draw a skeleton), so it drops
|
|
9
|
+
// pure deletions and expands to whole blocks. The Review moment instead needs, per
|
|
10
|
+
// contiguous change, BOTH the original slice (pre-edit, for undo / "compare with
|
|
11
|
+
// original") and the new slice (for redo), AND it must keep deletions (a removed
|
|
12
|
+
// paragraph is a reviewable change). So this derives the actual changed extents
|
|
13
|
+
// and reconstructs the pre-edit slice from `tr.before`.
|
|
14
|
+
//
|
|
15
|
+
// The output is a neutral `AgentRemoteEditReviewData` (contract in editor-common);
|
|
16
|
+
// `editor-plugin-ai`'s session-context plugin turns each segment into a coarse
|
|
17
|
+
// `aiContentPositions` entry, reusing the entire FE Review moment pipeline.
|
|
18
|
+
|
|
19
|
+
var clampToDoc = function clampToDoc(doc, pos) {
|
|
20
|
+
return Math.min(Math.max(pos, 0), doc.content.size);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Map a position in doc_{i+1} forward through the remaining steps to final-doc
|
|
24
|
+
// coords. Mirrors the shimmer's `mapToFinalDoc` — a later step's own inserted
|
|
25
|
+
// content starts at its `from`; only subsequent steps shift it.
|
|
26
|
+
var mapToFinalDoc = function mapToFinalDoc(steps, pos, stepIndex, bias) {
|
|
27
|
+
var p = pos;
|
|
28
|
+
for (var j = stepIndex + 1; j < steps.length; j++) {
|
|
29
|
+
p = steps[j].getMap().map(p, bias);
|
|
30
|
+
}
|
|
31
|
+
return p;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Derive per-change Review moment segments from an agent-authored remote-step
|
|
36
|
+
* batch. Returns `null` when there is nothing to record (no agent steps, or a
|
|
37
|
+
* rebase invalidated our index math, or derivation threw) so the caller can no-op
|
|
38
|
+
* safely — this must never throw into the shared remote-step handler.
|
|
39
|
+
*
|
|
40
|
+
* @param json the raw received step JSON (carries `agentType` / `agentId` / `userId`)
|
|
41
|
+
* @param steps the parsed PM steps (index-aligned with `json`)
|
|
42
|
+
* @param tr the transaction that applied `steps` (so `tr.before`/`tr.doc`/`tr.mapping` are available)
|
|
43
|
+
* @param view the editor view (for the collab rebase guard)
|
|
44
|
+
*/
|
|
45
|
+
export var getAgentEditSegments = function getAgentEditSegments(json, steps, tr, view) {
|
|
46
|
+
// `agentType` present ⇒ agent-authored (per the NCS↔Editor steps contract). Read
|
|
47
|
+
// from the first agent step; it is identical across a batch.
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
var agentStep = json.find(function (step) {
|
|
50
|
+
return typeof (step === null || step === void 0 ? void 0 : step.agentType) === 'string';
|
|
51
|
+
});
|
|
52
|
+
var agentType = agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentType;
|
|
53
|
+
if (agentType === undefined) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
// The user the agent acted on behalf of (the requester). Optional/additive on the
|
|
57
|
+
// step contract, so it may be absent.
|
|
58
|
+
var actorUserId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.userId) === 'string' ? agentStep.userId : undefined;
|
|
59
|
+
// Which agent instance wrote the batch. Additive on the step contract like
|
|
60
|
+
// `userId`, so treat it as optional. Carried for contract clarity / future
|
|
61
|
+
// per-agent attribution; nothing consumes it yet.
|
|
62
|
+
var agentId = typeof (agentStep === null || agentStep === void 0 ? void 0 : agentStep.agentId) === 'string' ? agentStep.agentId : undefined;
|
|
63
|
+
// Hybrid end-of-edit seam: if the BE/NCS flags a batch as the terminal one, carry
|
|
64
|
+
// it so the AI plugin can open review immediately instead of waiting for the
|
|
65
|
+
// debounce. Additive marker; absent for streaming (non-final) batches.
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
var complete = json.some(function (step) {
|
|
68
|
+
return (step === null || step === void 0 ? void 0 : step.agentEditComplete) === true;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Same rebase guard as the shimmer: index-based range math is only valid if any
|
|
72
|
+
// rebased-over local steps shifted no positions. Degrade to no recording otherwise.
|
|
73
|
+
if (Number(tr.getMeta('rebased')) > 0) {
|
|
74
|
+
var _getCollabState$uncon, _getCollabState;
|
|
75
|
+
var unconfirmed = (_getCollabState$uncon = (_getCollabState = getCollabState(view.state)) === null || _getCollabState === void 0 ? void 0 : _getCollabState.unconfirmed) !== null && _getCollabState$uncon !== void 0 ? _getCollabState$uncon : [];
|
|
76
|
+
if (unconfirmed.some(function (entry) {
|
|
77
|
+
return !isPositionNeutralStep(entry.step);
|
|
78
|
+
})) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
// Compute one segment per step-level StepMap range. Each agent step's changed
|
|
84
|
+
// extent is taken from its StepMap (the canonical, step-type-agnostic source).
|
|
85
|
+
// Unlike the shimmer we KEEP zero-width new extents — a pure deletion has
|
|
86
|
+
// `newEnd === newStart` but is a reviewable `remove`.
|
|
87
|
+
//
|
|
88
|
+
// We derive the originalSlice/newSlice PER RANGE (per step) rather than
|
|
89
|
+
// grouping ranges first and then inverting over a merged range. Grouping
|
|
90
|
+
// before slicing corrupts the invert-mapping: when multiple discrete
|
|
91
|
+
// operations (e.g. two deleteNode + one insertNodeAfter) are merged into one
|
|
92
|
+
// range, mapping that merged range back through the inverted mapping produces
|
|
93
|
+
// a chimera — a blend of old and new text that never existed in the document.
|
|
94
|
+
//
|
|
95
|
+
// The downstream PSR pipeline (mergeOverlappingSegments +
|
|
96
|
+
// calculateTopLevelNodeSegments) already handles overlapping/adjacent coarse
|
|
97
|
+
// entries correctly, so grouping here is unnecessary.
|
|
98
|
+
|
|
99
|
+
var segments = [];
|
|
100
|
+
json.forEach(function (rawStep, index) {
|
|
101
|
+
if (typeof (rawStep === null || rawStep === void 0 ? void 0 : rawStep.agentType) !== 'string') {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
+
var pmStep = steps[index];
|
|
106
|
+
if (typeof (pmStep === null || pmStep === void 0 ? void 0 : pmStep.getMap) !== 'function') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
pmStep.getMap().forEach(function (oldStart, oldEnd, newStart, newEnd) {
|
|
110
|
+
try {
|
|
111
|
+
// NEW-doc coordinates: map this step's newStart/newEnd forward
|
|
112
|
+
// through all subsequent steps to get final-doc positions.
|
|
113
|
+
var finalFrom = mapToFinalDoc(steps, newStart, index, -1);
|
|
114
|
+
var finalTo = mapToFinalDoc(steps, newEnd, index, 1);
|
|
115
|
+
var newFrom = clampToDoc(tr.doc, Math.min(finalFrom, finalTo));
|
|
116
|
+
var newTo = clampToDoc(tr.doc, Math.max(finalFrom, finalTo));
|
|
117
|
+
|
|
118
|
+
// ORIGINAL-doc coordinates: map this step's oldStart/oldEnd
|
|
119
|
+
// BACKWARD through all preceding steps to get pre-batch
|
|
120
|
+
// (`tr.before`) positions. Each preceding step's StepMap tells
|
|
121
|
+
// us how positions shifted; we invert that shift by mapping
|
|
122
|
+
// through the inverted StepMap.
|
|
123
|
+
//
|
|
124
|
+
// This is the key difference from using `tr.mapping.invert()`
|
|
125
|
+
// which inverts ALL steps at once — that produces chimera text
|
|
126
|
+
// when multiple discrete operations (delete + delete + insert)
|
|
127
|
+
// interact in the same region. Per-step backward mapping keeps
|
|
128
|
+
// each operation's original range isolated.
|
|
129
|
+
var origStart = oldStart;
|
|
130
|
+
var origEnd = oldEnd;
|
|
131
|
+
for (var j = index - 1; j >= 0; j--) {
|
|
132
|
+
var prevMap = steps[j].getMap().invert();
|
|
133
|
+
origStart = prevMap.map(origStart, -1);
|
|
134
|
+
origEnd = prevMap.map(origEnd, 1);
|
|
135
|
+
}
|
|
136
|
+
var origFrom = clampToDoc(tr.before, Math.min(origStart, origEnd));
|
|
137
|
+
var origTo = clampToDoc(tr.before, Math.max(origStart, origEnd));
|
|
138
|
+
var originalSlice = tr.before.slice(origFrom, origTo);
|
|
139
|
+
var newSlice = tr.doc.slice(newFrom, newTo);
|
|
140
|
+
var originalEmpty = originalSlice.content.size === 0;
|
|
141
|
+
var newEmpty = newSlice.content.size === 0;
|
|
142
|
+
// A truly empty-to-empty region is not a change — skip it.
|
|
143
|
+
if (originalEmpty && newEmpty) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
var kind = originalEmpty ? 'add' : newEmpty ? 'remove' : 'update';
|
|
147
|
+
segments.push({
|
|
148
|
+
startPos: newFrom,
|
|
149
|
+
endPos: newTo,
|
|
150
|
+
originalSlice: originalSlice,
|
|
151
|
+
newSlice: newSlice,
|
|
152
|
+
kind: kind
|
|
153
|
+
});
|
|
154
|
+
} catch (_unused) {
|
|
155
|
+
// One bad range must not drop the others.
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
if (!segments.length) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
actorUserId: actorUserId,
|
|
164
|
+
agentId: agentId,
|
|
165
|
+
agentType: agentType,
|
|
166
|
+
complete: complete,
|
|
167
|
+
segments: segments
|
|
168
|
+
};
|
|
169
|
+
} catch (_unused2) {
|
|
170
|
+
// Never throw into the shared remote-step handler; degrade to no recording.
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentRemoteEditReviewData } from '@atlaskit/editor-common/collab-agent-remote-edit-review';
|
|
2
|
+
import type { Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import type { Step } from '@atlaskit/editor-prosemirror/transform';
|
|
4
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
/**
|
|
6
|
+
* Derive per-change Review moment segments from an agent-authored remote-step
|
|
7
|
+
* batch. Returns `null` when there is nothing to record (no agent steps, or a
|
|
8
|
+
* rebase invalidated our index math, or derivation threw) so the caller can no-op
|
|
9
|
+
* safely — this must never throw into the shared remote-step handler.
|
|
10
|
+
*
|
|
11
|
+
* @param json the raw received step JSON (carries `agentType` / `agentId` / `userId`)
|
|
12
|
+
* @param steps the parsed PM steps (index-aligned with `json`)
|
|
13
|
+
* @param tr the transaction that applied `steps` (so `tr.before`/`tr.doc`/`tr.mapping` are available)
|
|
14
|
+
* @param view the editor view (for the collab rebase guard)
|
|
15
|
+
*/
|
|
16
|
+
export declare const getAgentEditSegments: (json: any[], steps: Step[], tr: Transaction, view: EditorView) => AgentRemoteEditReviewData | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-collab-edit",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.4.1",
|
|
4
4
|
"description": "Collab Edit plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"sideEffects": false,
|
|
20
20
|
"atlaskit:src": "src/index.ts",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@atlaskit/adf-schema": "^56.
|
|
22
|
+
"@atlaskit/adf-schema": "^56.5.0",
|
|
23
23
|
"@atlaskit/custom-steps": "^1.0.0",
|
|
24
24
|
"@atlaskit/editor-json-transformer": "^9.2.0",
|
|
25
25
|
"@atlaskit/editor-plugin-analytics": "^12.1.0",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"@atlaskit/frontend-utilities": "^4.1.0",
|
|
32
32
|
"@atlaskit/platform-feature-flags": "^2.1.0",
|
|
33
33
|
"@atlaskit/prosemirror-collab": "^1.0.0",
|
|
34
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
34
|
+
"@atlaskit/tmp-editor-statsig": "^137.0.0",
|
|
35
35
|
"@atlaskit/tokens": "^16.3.0",
|
|
36
36
|
"@babel/runtime": "^7.0.0",
|
|
37
37
|
"memoize-one": "^6.0.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@atlaskit/editor-common": "^116.
|
|
40
|
+
"@atlaskit/editor-common": "^116.51.0",
|
|
41
41
|
"react": "^18.2.0 || ^19.2.0",
|
|
42
42
|
"react-dom": "^18.2.0 || ^19.2.0"
|
|
43
43
|
},
|