@superdoc/mcp 1.0.0-next.7 → 1.0.0-next.9
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/dist/index.js +419 -104
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -349815,7 +349815,7 @@ var init_host = __esm(() => {
|
|
|
349815
349815
|
});
|
|
349816
349816
|
|
|
349817
349817
|
// ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
|
|
349818
|
-
var SDK_VERSION = "2.13.0-next.
|
|
349818
|
+
var SDK_VERSION = "2.13.0-next.11";
|
|
349819
349819
|
|
|
349820
349820
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
349821
349821
|
import { chmodSync, existsSync } from "node:fs";
|
|
@@ -489460,7 +489460,8 @@ function tryRangeReplacementAcrossTokens(input, allTokens, touched) {
|
|
|
489460
489460
|
if (touchedInsertions.some(({ token }) => token.innerRuns && token.innerRuns.length > 1 || token.nestedDeletions && token.nestedDeletions.length > 0)) {
|
|
489461
489461
|
return null;
|
|
489462
489462
|
}
|
|
489463
|
-
|
|
489463
|
+
const result = input.changeMode === "tracked" ? authorTrackedPureDelete(input, allTokens, touched) : authorDirectPureDelete(input, allTokens, touched);
|
|
489464
|
+
return result?.ok && input.changeMode === "tracked" ? { ...result, requiresCollaborationSessionSync: true } : result;
|
|
489464
489465
|
}
|
|
489465
489466
|
function renderBreakRunPureDelete(token, input, mode, wrapDeleted) {
|
|
489466
489467
|
const { controlXml, runOpen, runClose, rPr, text, controlVisibleStart } = token.inertBreakRun;
|
|
@@ -491550,11 +491551,16 @@ function buildCoalescedDeletionReplacement(change, partXml) {
|
|
|
491550
491551
|
return null;
|
|
491551
491552
|
if (index > 0) {
|
|
491552
491553
|
const previous = orderedFragments[index - 1];
|
|
491553
|
-
|
|
491554
|
+
const interstitialXml = partXml.slice(previous.byteEnd, fragment2.byteStart);
|
|
491555
|
+
if (/<(?:[\w.-]+:)?(?:fldChar|fldSimple|instrText)\b/.test(interstitialXml))
|
|
491556
|
+
return null;
|
|
491557
|
+
xml += interstitialXml;
|
|
491554
491558
|
}
|
|
491555
491559
|
xml += parts.innerXml;
|
|
491556
491560
|
}
|
|
491557
491561
|
xml += firstParts.closeTag;
|
|
491562
|
+
if (parseXmlForError(`<root>${xml}</root>`, { namespaceAware: false }) !== null)
|
|
491563
|
+
return null;
|
|
491558
491564
|
return { start: first.byteStart, end: last.byteEnd, xml };
|
|
491559
491565
|
}
|
|
491560
491566
|
function readTrackedWrapperParts(partXml, fragment2, expectedKind) {
|
|
@@ -491689,6 +491695,7 @@ function escapeRegExp6(value) {
|
|
|
491689
491695
|
}
|
|
491690
491696
|
var DECODER, ENCODER;
|
|
491691
491697
|
var init_export_projection = __esm(() => {
|
|
491698
|
+
init_xml_sax();
|
|
491692
491699
|
init_catalog3();
|
|
491693
491700
|
init_logical_catalog();
|
|
491694
491701
|
init_move_stamps();
|
|
@@ -493652,6 +493659,9 @@ function commitTracked(input, view) {
|
|
|
493652
493659
|
}
|
|
493653
493660
|
if (!localized.ok)
|
|
493654
493661
|
return rejected2(txId, localized.reason);
|
|
493662
|
+
if (compileOp.on.coordinateSpace !== "tracked" && requiresStructuralTrackedRewriteSessionSync(paragraphXml, inlineContext.model.leaves(), compileOp.on.startOffset, compileOp.on.endOffset)) {
|
|
493663
|
+
localized = { ...localized, requiresCollaborationSessionSync: true };
|
|
493664
|
+
}
|
|
493655
493665
|
if (op.newText.includes("\t"))
|
|
493656
493666
|
localized = { ...localized, requiresCollaborationSessionSync: true };
|
|
493657
493667
|
if (localized.foldedInsRsid != null) {
|
|
@@ -494691,6 +494701,36 @@ function rewriteLocalizedDirect(bytes, window2, op, inheritedNamespaceBindings =
|
|
|
494691
494701
|
}
|
|
494692
494702
|
return { ok: false, reason: plan.reason };
|
|
494693
494703
|
}
|
|
494704
|
+
function requiresStructuralTrackedRewriteSessionSync(paragraphXml, leaves, startOffset, endOffset) {
|
|
494705
|
+
if (startOffset >= endOffset)
|
|
494706
|
+
return false;
|
|
494707
|
+
const transparentMarkerRe = /<[\w.-]+:(?:proofErr|lastRenderedPageBreak)\b[^>]*\/?>/g;
|
|
494708
|
+
for (const match of paragraphXml.matchAll(transparentMarkerRe)) {
|
|
494709
|
+
const markerStart = match.index;
|
|
494710
|
+
const markerEnd = markerStart + match[0].length;
|
|
494711
|
+
let before;
|
|
494712
|
+
for (let index = leaves.length - 1;index >= 0; index -= 1) {
|
|
494713
|
+
if (leaves[index].charEnd <= markerStart) {
|
|
494714
|
+
before = leaves[index];
|
|
494715
|
+
break;
|
|
494716
|
+
}
|
|
494717
|
+
}
|
|
494718
|
+
const after = leaves.find((piece) => piece.charStart >= markerEnd);
|
|
494719
|
+
const markerOffset = before?.visibleEnd ?? after?.visibleStart;
|
|
494720
|
+
if (markerOffset != null && startOffset < markerOffset && endOffset > markerOffset)
|
|
494721
|
+
return true;
|
|
494722
|
+
}
|
|
494723
|
+
const affected = leaves.filter((piece) => {
|
|
494724
|
+
const overlapsVisibleRange = startOffset < piece.visibleEnd && endOffset > piece.visibleStart;
|
|
494725
|
+
const crossesZeroWidthPiece = startOffset < piece.visibleStart && endOffset > piece.visibleEnd;
|
|
494726
|
+
return overlapsVisibleRange || crossesZeroWidthPiece;
|
|
494727
|
+
});
|
|
494728
|
+
if (affected.some((piece) => piece.kind !== "text" && piece.kind !== "control"))
|
|
494729
|
+
return true;
|
|
494730
|
+
const structuralStack = (piece) => JSON.stringify(piece.containerStack.filter((scope) => scope.kind !== "ins" && scope.kind !== "del" && scope.kind !== "moveFrom" && scope.kind !== "moveTo").map((scope) => [scope.kind, scope.qname]));
|
|
494731
|
+
const textStacks = affected.filter((piece) => piece.kind === "text").map(structuralStack);
|
|
494732
|
+
return textStacks.some((stack) => stack !== textStacks[0]);
|
|
494733
|
+
}
|
|
494694
494734
|
function rewriteLocalizedTracked(bytes, window2, op, stamp, preparedContext) {
|
|
494695
494735
|
const paragraphBytes = bytes.subarray(window2.byteStart, window2.byteEnd);
|
|
494696
494736
|
const inlineContext = preparedContext ?? prepareParagraphInlineEditContext(paragraphBytes);
|
|
@@ -496464,7 +496504,7 @@ function rewriteRunSpanTrackedReplace(paragraphXml, startOffset, endOffset, stam
|
|
|
496464
496504
|
return { ok: false, reason: "tracked-inline-control-unsupported" };
|
|
496465
496505
|
}
|
|
496466
496506
|
}
|
|
496467
|
-
if (collected.markerIntegrity.hasPreservableMarker) {
|
|
496507
|
+
if (collected.markerIntegrity.hasPreservableMarker || stamp.newText.length > 0 && requiresStructuralTrackedRewriteSessionSync(paragraphXml, parseParagraphInlineMap(paragraphXml).leaves(), startOffset, endOffset)) {
|
|
496468
496508
|
return rewriteRunSpanTrackedReplacePreservingMarkers(paragraphXml, span, stamp, paragraphMarkFallback.rPr);
|
|
496469
496509
|
}
|
|
496470
496510
|
const first = span.runs[span.firstRunIdx];
|
|
@@ -503109,7 +503149,7 @@ function runTrackedChangeDecideCommit(input) {
|
|
|
503109
503149
|
fragmentsByPart,
|
|
503110
503150
|
structuralTargets
|
|
503111
503151
|
});
|
|
503112
|
-
const sessionSyncedTextDecision = trackedTextDecide && (hasNestedTextDecision(catalog, fragmentsByPart) || hasStructuralInlineDeletionDecision(state, fragmentsByPart));
|
|
503152
|
+
const sessionSyncedTextDecision = trackedTextDecide && (hasNestedTextDecision(catalog, fragmentsByPart) || hasStructuralInlineDeletionDecision(state, fragmentsByPart) || hasMarkerSeparatedTextDecision(state, fragmentsByPart));
|
|
503113
503153
|
const prepared = {
|
|
503114
503154
|
txId,
|
|
503115
503155
|
source: op,
|
|
@@ -503479,6 +503519,45 @@ function hasStructuralInlineDeletionDecision(state, fragmentsByPart) {
|
|
|
503479
503519
|
}
|
|
503480
503520
|
return false;
|
|
503481
503521
|
}
|
|
503522
|
+
function hasMarkerSeparatedTextDecision(state, fragmentsByPart) {
|
|
503523
|
+
for (const [partUri, fragments] of fragmentsByPart) {
|
|
503524
|
+
const partBytes = state.packageBytes.get(partUri);
|
|
503525
|
+
if (!partBytes)
|
|
503526
|
+
continue;
|
|
503527
|
+
const textFragments = fragments.filter((fragment2) => fragment2.kind === "ins" || fragment2.kind === "del");
|
|
503528
|
+
const paragraphByFragment = findParagraphsContainingFragments(state, textFragments);
|
|
503529
|
+
const grouped = new Map;
|
|
503530
|
+
for (const fragment2 of textFragments) {
|
|
503531
|
+
const paragraph = paragraphByFragment.get(fragment2);
|
|
503532
|
+
if (!paragraph)
|
|
503533
|
+
continue;
|
|
503534
|
+
const key2 = `${fragment2.storyId}|${paragraph.blockId}|${fragment2.kind}|${fragment2.rsid}`;
|
|
503535
|
+
const group = grouped.get(key2) ?? [];
|
|
503536
|
+
group.push(fragment2);
|
|
503537
|
+
grouped.set(key2, group);
|
|
503538
|
+
}
|
|
503539
|
+
for (const group of grouped.values()) {
|
|
503540
|
+
if (group.length < 2)
|
|
503541
|
+
continue;
|
|
503542
|
+
const ordered = [...group].sort((left, right) => {
|
|
503543
|
+
const leftRange = preparedFragmentSourceRange(left);
|
|
503544
|
+
const rightRange = preparedFragmentSourceRange(right);
|
|
503545
|
+
return leftRange.start - rightRange.start;
|
|
503546
|
+
});
|
|
503547
|
+
for (let index = 1;index < ordered.length; index += 1) {
|
|
503548
|
+
const previous = preparedFragmentSourceRange(ordered[index - 1]);
|
|
503549
|
+
const current = preparedFragmentSourceRange(ordered[index]);
|
|
503550
|
+
if (!previous || !current || previous.end > current.start)
|
|
503551
|
+
continue;
|
|
503552
|
+
const separator = TD44.decode(partBytes.subarray(previous.end, current.start));
|
|
503553
|
+
if (/<[\w.-]+:(?:bookmarkStart|bookmarkEnd|commentRangeStart|commentRangeEnd|commentReference)\b/.test(separator)) {
|
|
503554
|
+
return true;
|
|
503555
|
+
}
|
|
503556
|
+
}
|
|
503557
|
+
}
|
|
503558
|
+
}
|
|
503559
|
+
return false;
|
|
503560
|
+
}
|
|
503482
503561
|
function buildPreparedTrackedTextDecide(input) {
|
|
503483
503562
|
if (input.op.targets.some((target) => target.partial || target.formatting || target.derivedStructural || (target.moveRangeMarkers?.ids.length ?? 0) > 0)) {
|
|
503484
503563
|
return;
|
|
@@ -691770,7 +691849,7 @@ function parseParagraphXml(xml, inheritedNamespaceBindings = {}, trackedWrapperI
|
|
|
691770
691849
|
} else if (tagLocalName === "hyperlink") {
|
|
691771
691850
|
const inner = stripOuterTag(next.xml);
|
|
691772
691851
|
const closingTag = extractClosingTag(next.xml);
|
|
691773
|
-
const innerSegments = parseInnerInline(inner, namespaceBindingsForElement(next.openTagInner, paragraphNamespaceBindings));
|
|
691852
|
+
const innerSegments = parseInnerInline(inner, namespaceBindingsForElement(next.openTagInner, paragraphNamespaceBindings), trackedWrapperIdentityState);
|
|
691774
691853
|
segments.push({
|
|
691775
691854
|
kind: "atom",
|
|
691776
691855
|
atomKind: INLINE_ATOM_KIND.preserved,
|
|
@@ -707175,44 +707254,130 @@ function syncParagraphMarkerCarriers(carriers, next, create10) {
|
|
|
707175
707254
|
offset += carrier.text.length;
|
|
707176
707255
|
return { ...carrier, start, end: offset, next: [] };
|
|
707177
707256
|
});
|
|
707178
|
-
for (
|
|
707179
|
-
const position2 = Number(
|
|
707180
|
-
|
|
707181
|
-
|
|
707257
|
+
for (let markerIndex = 0;markerIndex < next.length; ) {
|
|
707258
|
+
const position2 = Number(next[markerIndex].visibleOffset ?? 0);
|
|
707259
|
+
let groupEnd = markerIndex + 1;
|
|
707260
|
+
while (groupEnd < next.length && Number(next[groupEnd].visibleOffset ?? 0) === position2)
|
|
707261
|
+
groupEnd += 1;
|
|
707262
|
+
const group = next.slice(markerIndex, groupEnd);
|
|
707263
|
+
const retainedOwners = windows.filter((window2) => group.some((marker) => window2.markers.toArray().some((existing) => readInlineControlOffset(existing) + window2.start === position2 && sameMarker(existing, marker))));
|
|
707264
|
+
const sharedOwner = retainedOwners.length === 1 ? retainedOwners[0] : null;
|
|
707265
|
+
for (const marker of group) {
|
|
707266
|
+
const owner = sharedOwner ?? windows.find((window2) => window2.markers.toArray().some((existing) => readInlineControlOffset(existing) + window2.start === position2 && sameMarker(existing, marker))) ?? windows.find((window2) => position2 < window2.end) ?? windows[windows.length - 1];
|
|
707267
|
+
owner.next.push({ ...marker, visibleOffset: position2 - owner.start });
|
|
707268
|
+
}
|
|
707269
|
+
markerIndex = groupEnd;
|
|
707182
707270
|
}
|
|
707183
707271
|
for (const window2 of windows)
|
|
707184
707272
|
syncParagraphMarkers(window2.markers, window2.next, create10);
|
|
707185
707273
|
}
|
|
707186
707274
|
function syncParagraphMarkers(array3, next, create10) {
|
|
707187
707275
|
const previous3 = array3.toArray();
|
|
707188
|
-
|
|
707189
|
-
|
|
707190
|
-
|
|
707191
|
-
|
|
707192
|
-
|
|
707193
|
-
|
|
707194
|
-
|
|
707195
|
-
|
|
707196
|
-
|
|
707197
|
-
|
|
707198
|
-
|
|
707199
|
-
|
|
707200
|
-
|
|
707276
|
+
const retained = longestSharedMarkerSubsequence(previous3, next);
|
|
707277
|
+
const anchors2 = [
|
|
707278
|
+
{ previous: -1, next: -1 },
|
|
707279
|
+
...retained,
|
|
707280
|
+
{ previous: previous3.length, next: next.length }
|
|
707281
|
+
];
|
|
707282
|
+
for (let anchorIndex = anchors2.length - 2;anchorIndex >= 0; anchorIndex -= 1) {
|
|
707283
|
+
const left = anchors2[anchorIndex];
|
|
707284
|
+
const right = anchors2[anchorIndex + 1];
|
|
707285
|
+
const start = left.previous + 1;
|
|
707286
|
+
const removed = right.previous - start;
|
|
707287
|
+
if (removed > 0)
|
|
707288
|
+
array3.delete(start, removed);
|
|
707289
|
+
const additions = next.slice(left.next + 1, right.next);
|
|
707290
|
+
const inserted = additions.map(create10);
|
|
707291
|
+
if (inserted.length > 0)
|
|
707292
|
+
array3.insert(start, inserted);
|
|
707293
|
+
assignInsertedTrackedMarkerIds(array3, inserted, additions, start);
|
|
707294
|
+
}
|
|
707295
|
+
next.forEach((value2, index2) => {
|
|
707296
|
+
const marker = array3.get(index2);
|
|
707297
|
+
if (marker.get("visibleOffset") !== value2.visibleOffset)
|
|
707298
|
+
marker.set("visibleOffset", value2.visibleOffset);
|
|
707299
|
+
anchorInlineControl(marker, Number(value2.visibleOffset));
|
|
707300
|
+
});
|
|
707301
|
+
}
|
|
707302
|
+
function longestSharedMarkerSubsequence(previous3, next) {
|
|
707303
|
+
const exactCells = (previous3.length + 1) * (next.length + 1);
|
|
707304
|
+
if (exactCells > 1e6)
|
|
707305
|
+
return orderedSharedMarkerSubsequence(previous3, next);
|
|
707306
|
+
const lengths = Array.from({ length: previous3.length + 1 }, () => new Uint32Array(next.length + 1));
|
|
707307
|
+
for (let previousIndex2 = previous3.length - 1;previousIndex2 >= 0; previousIndex2 -= 1) {
|
|
707308
|
+
for (let nextIndex2 = next.length - 1;nextIndex2 >= 0; nextIndex2 -= 1) {
|
|
707309
|
+
lengths[previousIndex2][nextIndex2] = sameMarker(previous3[previousIndex2], next[nextIndex2]) ? 1 + lengths[previousIndex2 + 1][nextIndex2 + 1] : Math.max(lengths[previousIndex2 + 1][nextIndex2], lengths[previousIndex2][nextIndex2 + 1]);
|
|
707310
|
+
}
|
|
707311
|
+
}
|
|
707312
|
+
const retained = [];
|
|
707313
|
+
let previousIndex = 0;
|
|
707314
|
+
let nextIndex = 0;
|
|
707315
|
+
while (previousIndex < previous3.length && nextIndex < next.length) {
|
|
707316
|
+
if (sameMarker(previous3[previousIndex], next[nextIndex]) && lengths[previousIndex][nextIndex] === 1 + lengths[previousIndex + 1][nextIndex + 1]) {
|
|
707317
|
+
retained.push({ previous: previousIndex, next: nextIndex });
|
|
707318
|
+
previousIndex += 1;
|
|
707319
|
+
nextIndex += 1;
|
|
707320
|
+
} else if (lengths[previousIndex + 1][nextIndex] >= lengths[previousIndex][nextIndex + 1]) {
|
|
707321
|
+
previousIndex += 1;
|
|
707322
|
+
} else {
|
|
707323
|
+
nextIndex += 1;
|
|
707324
|
+
}
|
|
707325
|
+
}
|
|
707326
|
+
return retained;
|
|
707327
|
+
}
|
|
707328
|
+
function orderedSharedMarkerSubsequence(previous3, next) {
|
|
707329
|
+
const positions = new Map;
|
|
707330
|
+
previous3.forEach((marker, index2) => {
|
|
707331
|
+
const key2 = markerDiscriminator((name) => marker.get(name));
|
|
707332
|
+
const indexes = positions.get(key2);
|
|
707333
|
+
if (indexes)
|
|
707334
|
+
indexes.push(index2);
|
|
707335
|
+
else
|
|
707336
|
+
positions.set(key2, [index2]);
|
|
707337
|
+
});
|
|
707338
|
+
const retained = [];
|
|
707339
|
+
let minimumPrevious = 0;
|
|
707340
|
+
next.forEach((marker, nextIndex) => {
|
|
707341
|
+
const indexes = positions.get(markerDiscriminator((name) => marker[name]));
|
|
707342
|
+
if (!indexes)
|
|
707343
|
+
return;
|
|
707344
|
+
let low = 0;
|
|
707345
|
+
let high = indexes.length;
|
|
707346
|
+
while (low < high) {
|
|
707347
|
+
const middle = low + high >>> 1;
|
|
707348
|
+
if (indexes[middle] < minimumPrevious)
|
|
707349
|
+
low = middle + 1;
|
|
707350
|
+
else
|
|
707351
|
+
high = middle;
|
|
707352
|
+
}
|
|
707353
|
+
while (low < indexes.length && !sameMarker(previous3[indexes[low]], marker))
|
|
707354
|
+
low += 1;
|
|
707355
|
+
if (low === indexes.length)
|
|
707356
|
+
return;
|
|
707357
|
+
const previousIndex = indexes[low];
|
|
707358
|
+
retained.push({ previous: previousIndex, next: nextIndex });
|
|
707359
|
+
minimumPrevious = previousIndex + 1;
|
|
707360
|
+
});
|
|
707361
|
+
return retained;
|
|
707362
|
+
}
|
|
707363
|
+
function markerDiscriminator(read) {
|
|
707364
|
+
return JSON.stringify([
|
|
707365
|
+
read("kind"),
|
|
707366
|
+
read("xml"),
|
|
707367
|
+
read("length"),
|
|
707368
|
+
read("meta")
|
|
707369
|
+
]);
|
|
707370
|
+
}
|
|
707371
|
+
function assignInsertedTrackedMarkerIds(array3, inserted, additions, start) {
|
|
707201
707372
|
inserted.forEach((marker, index2) => {
|
|
707202
707373
|
const value2 = additions[index2];
|
|
707203
707374
|
const meta3 = value2.meta;
|
|
707204
707375
|
const trackedCarrier = value2.kind === "tracked-wrapper" || value2.kind === "preserved" && (meta3?.tag === "delTextRun" || meta3?.container === "tracked-deletion");
|
|
707205
707376
|
if (trackedCarrier) {
|
|
707206
|
-
const item = createRelativePositionFromTypeIndex(array3,
|
|
707377
|
+
const item = createRelativePositionFromTypeIndex(array3, start + index2).item;
|
|
707207
707378
|
marker.set("id", `${value2.id}:sync:${item.client.toString(36)}:${item.clock.toString(36)}`);
|
|
707208
707379
|
}
|
|
707209
707380
|
});
|
|
707210
|
-
next.forEach((value2, index2) => {
|
|
707211
|
-
const marker = array3.get(index2);
|
|
707212
|
-
if (marker.get("visibleOffset") !== value2.visibleOffset)
|
|
707213
|
-
marker.set("visibleOffset", value2.visibleOffset);
|
|
707214
|
-
anchorInlineControl(marker, Number(value2.visibleOffset));
|
|
707215
|
-
});
|
|
707216
707381
|
}
|
|
707217
707382
|
var init_paragraph_inline_sync = __esm(() => {
|
|
707218
707383
|
init_yjs();
|
|
@@ -707239,13 +707404,14 @@ function mirrorStorySurfaceFromSession(input) {
|
|
|
707239
707404
|
};
|
|
707240
707405
|
}
|
|
707241
707406
|
try {
|
|
707407
|
+
const extension2 = storyScopedTrackedDecisionExtension(input.extension, storyId);
|
|
707242
707408
|
const scope = resolveStoryShardScope(doc2);
|
|
707243
707409
|
scope.doc.transact(() => {
|
|
707244
|
-
const groups =
|
|
707410
|
+
const groups = extension2.contentControlRewrite || hasContentControlGroups(scope) ? prepareStoryContentControlGroups(input.session, storyId, doc2) : null;
|
|
707245
707411
|
mirrorFamilyIntoStory({
|
|
707246
707412
|
session: input.session,
|
|
707247
707413
|
prepared: input.prepared,
|
|
707248
|
-
extension:
|
|
707414
|
+
extension: extension2,
|
|
707249
707415
|
paragraphOnlyReviewStoryIds: input.paragraphOnlyReviewStoryIds,
|
|
707250
707416
|
storyId,
|
|
707251
707417
|
doc: doc2
|
|
@@ -707265,6 +707431,16 @@ function mirrorStorySurfaceFromSession(input) {
|
|
|
707265
707431
|
}
|
|
707266
707432
|
return { mirrored: true };
|
|
707267
707433
|
}
|
|
707434
|
+
function storyScopedTrackedDecisionExtension(extension2, storyId) {
|
|
707435
|
+
if (extension2.family !== "storyTrackedDecide" || !extension2.trackedTextDecide)
|
|
707436
|
+
return extension2;
|
|
707437
|
+
const targets = extension2.trackedTextDecide.targets.filter((target) => target.storyId === storyId);
|
|
707438
|
+
return {
|
|
707439
|
+
...extension2,
|
|
707440
|
+
targetBlockIds: [...new Set(targets.map((target) => target.blockId))],
|
|
707441
|
+
trackedTextDecide: { ...extension2.trackedTextDecide, targets }
|
|
707442
|
+
};
|
|
707443
|
+
}
|
|
707268
707444
|
function prepareStoryContentControlGroups(session, storyId, doc2) {
|
|
707269
707445
|
const scope = resolveStoryShardScope(doc2);
|
|
707270
707446
|
const source = readContentControlBlockGroups(loadStorySyncContext(session, storyId).bytes);
|
|
@@ -708730,7 +708906,7 @@ function runStorySurfaceMirror(prepared, options, admission, paragraphOnlyReview
|
|
|
708730
708906
|
};
|
|
708731
708907
|
}
|
|
708732
708908
|
}
|
|
708733
|
-
const familyResult = runFamilyMirror(prepared, extension2, options, admission.directStoryText, paragraphOnlyReviewStoryIds);
|
|
708909
|
+
const familyResult = runFamilyMirror(prepared, extension2, options, admission.directStoryText, admission.trackedDecision, paragraphOnlyReviewStoryIds);
|
|
708734
708910
|
if (!familyResult.mirrored) {
|
|
708735
708911
|
return {
|
|
708736
708912
|
txId: prepared.txId,
|
|
@@ -708769,7 +708945,7 @@ function hasStrictMirrorPrerequisites(prepared, options) {
|
|
|
708769
708945
|
case "storyText":
|
|
708770
708946
|
return !extension2.historyReplay && !extension2.resyncFromSession && !extension2.sessionSync ? true : options.session != null;
|
|
708771
708947
|
case "storyTrackedDecide":
|
|
708772
|
-
return !usesTrackedDecisionSessionSync(prepared, extension2) || options.session != null;
|
|
708948
|
+
return !usesTrackedDecisionSessionSync(prepared, extension2, options) || options.session != null;
|
|
708773
708949
|
case "storyTable":
|
|
708774
708950
|
return true;
|
|
708775
708951
|
case "storyBlocks":
|
|
@@ -708788,7 +708964,7 @@ function hasStrictMirrorPrerequisites(prepared, options) {
|
|
|
708788
708964
|
}
|
|
708789
708965
|
}
|
|
708790
708966
|
}
|
|
708791
|
-
function runFamilyMirror(prepared, extension2, options, directStoryText, paragraphOnlyReviewStoryIds) {
|
|
708967
|
+
function runFamilyMirror(prepared, extension2, options, directStoryText, trackedDecision, paragraphOnlyReviewStoryIds) {
|
|
708792
708968
|
if (!options.resolveStoryShard) {
|
|
708793
708969
|
return {
|
|
708794
708970
|
mirrored: false,
|
|
@@ -708836,7 +709012,7 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, paragra
|
|
|
708836
709012
|
return { mirrored: true };
|
|
708837
709013
|
}
|
|
708838
709014
|
if (extension2.family === "storyTrackedDecide") {
|
|
708839
|
-
if (usesTrackedDecisionSessionSync(prepared, extension2)) {
|
|
709015
|
+
if (usesTrackedDecisionSessionSync(prepared, extension2, options)) {
|
|
708840
709016
|
if (!options.session) {
|
|
708841
709017
|
return {
|
|
708842
709018
|
mirrored: false,
|
|
@@ -708850,14 +709026,32 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, paragra
|
|
|
708850
709026
|
const sessionSync = mirrorStorySurfaceFromSession({
|
|
708851
709027
|
session: options.session,
|
|
708852
709028
|
prepared,
|
|
708853
|
-
extension: extension2,
|
|
709029
|
+
extension: extension2.sessionSync || !extension2.trackedTextDecide ? extension2 : { ...extension2, sessionSync: { reason: "structural-inline-edit" } },
|
|
708854
709030
|
storyIds: storyIdsRequiringShards(prepared, extension2),
|
|
708855
709031
|
paragraphOnlyReviewStoryIds,
|
|
708856
709032
|
resolveStoryShard: options.resolveStoryShard
|
|
708857
709033
|
});
|
|
709034
|
+
if (sessionSync.mirrored && extension2.trackedTextDecide) {
|
|
709035
|
+
for (const target of extension2.trackedTextDecide.targets) {
|
|
709036
|
+
const doc2 = options.resolveStoryShard(target.storyId);
|
|
709037
|
+
if (doc2) {
|
|
709038
|
+
recordTrackedDecision(doc2, target.rsid, extension2.trackedTextDecide.decision, prepared.txId);
|
|
709039
|
+
}
|
|
709040
|
+
}
|
|
709041
|
+
}
|
|
708858
709042
|
return { ...sessionSync, mirrorPath: "session-sync" };
|
|
708859
709043
|
}
|
|
708860
|
-
|
|
709044
|
+
if (!trackedDecision) {
|
|
709045
|
+
return {
|
|
709046
|
+
mirrored: false,
|
|
709047
|
+
mirrorPath: "story-tracked-decide",
|
|
709048
|
+
failure: {
|
|
709049
|
+
storyId: prepared.resolvedTargets.stories[0] ?? "",
|
|
709050
|
+
message: "storyTrackedDecide requires an admitted cross-story preflight"
|
|
709051
|
+
}
|
|
709052
|
+
};
|
|
709053
|
+
}
|
|
709054
|
+
return mirrorPreparedTrackedDecide(prepared, trackedDecision);
|
|
708861
709055
|
}
|
|
708862
709056
|
if (extension2.family === "compareApply") {
|
|
708863
709057
|
return {
|
|
@@ -709072,30 +709266,11 @@ function mirrorPreparedCommentInsert(prepared, extension2, options) {
|
|
|
709072
709266
|
});
|
|
709073
709267
|
return { mirrored: true, mirrorPath: "session-sync" };
|
|
709074
709268
|
}
|
|
709075
|
-
function mirrorPreparedTrackedDecide(prepared,
|
|
709076
|
-
const
|
|
709077
|
-
|
|
709078
|
-
|
|
709079
|
-
|
|
709080
|
-
mirrorPath: "story-tracked-decide",
|
|
709081
|
-
failure: {
|
|
709082
|
-
storyId: prepared.resolvedTargets.stories[0] ?? "",
|
|
709083
|
-
message: validation.failureReason
|
|
709084
|
-
}
|
|
709085
|
-
};
|
|
709086
|
-
}
|
|
709087
|
-
const source = validation.source;
|
|
709088
|
-
const storyDocs = validation.storyDocs;
|
|
709089
|
-
for (const { storyId, doc: doc2 } of storyDocs) {
|
|
709090
|
-
const targets = validation.targets.filter((target) => target.storyId === storyId);
|
|
709091
|
-
if (targets.length === 0)
|
|
709092
|
-
continue;
|
|
709093
|
-
const result = applyTrackedTextDecisionsToStory({
|
|
709094
|
-
doc: doc2,
|
|
709095
|
-
targets,
|
|
709096
|
-
decision: source.decision,
|
|
709097
|
-
txId: prepared.txId,
|
|
709098
|
-
removedCommentIds: collectInvalidatedCommentIds(prepared)
|
|
709269
|
+
function mirrorPreparedTrackedDecide(prepared, preflight2) {
|
|
709270
|
+
for (const { storyId, plan } of preflight2.stories) {
|
|
709271
|
+
const result = applyPreflightedTrackedTextDecisionsToStory({
|
|
709272
|
+
plan,
|
|
709273
|
+
txId: prepared.txId
|
|
709099
709274
|
});
|
|
709100
709275
|
if (!result.ok) {
|
|
709101
709276
|
return {
|
|
@@ -709169,6 +709344,26 @@ function validatePreparedTrackedDecide(prepared, extension2, options) {
|
|
|
709169
709344
|
}
|
|
709170
709345
|
return { ok: true, source, storyDocs, targets: trackedTextDecide.targets };
|
|
709171
709346
|
}
|
|
709347
|
+
function preflightPreparedTrackedDecide(input) {
|
|
709348
|
+
const stories = [];
|
|
709349
|
+
const removedCommentIds = collectInvalidatedCommentIds(input.prepared);
|
|
709350
|
+
for (const { storyId, doc: doc2 } of input.storyDocs) {
|
|
709351
|
+
const targets = input.targets.filter((target) => target.storyId === storyId);
|
|
709352
|
+
if (targets.length === 0)
|
|
709353
|
+
continue;
|
|
709354
|
+
const result = preflightTrackedTextDecisionsToStory({
|
|
709355
|
+
doc: doc2,
|
|
709356
|
+
targets,
|
|
709357
|
+
decision: input.source.decision,
|
|
709358
|
+
removedCommentIds
|
|
709359
|
+
});
|
|
709360
|
+
if (!result.ok) {
|
|
709361
|
+
return { ok: false, failureReason: `${storyId}: ${result.failureReason}` };
|
|
709362
|
+
}
|
|
709363
|
+
stories.push({ storyId, plan: result.plan });
|
|
709364
|
+
}
|
|
709365
|
+
return { ok: true, preflight: { stories } };
|
|
709366
|
+
}
|
|
709172
709367
|
function isSupportedPreparedTrackedTextKind(kind) {
|
|
709173
709368
|
return kind === "ins" || kind === "del";
|
|
709174
709369
|
}
|
|
@@ -709205,47 +709400,133 @@ function isSupportedPreparedTrackedCarrier(target) {
|
|
|
709205
709400
|
return true;
|
|
709206
709401
|
return target.carrierKind === "field-insertion" && target.trackedKind === "ins";
|
|
709207
709402
|
}
|
|
709208
|
-
function
|
|
709403
|
+
function preflightTrackedTextDecisionsToStory(input) {
|
|
709209
709404
|
const resolved = [];
|
|
709210
|
-
|
|
709211
|
-
|
|
709212
|
-
|
|
709213
|
-
|
|
709405
|
+
const usedSpanIds = new Set;
|
|
709406
|
+
const candidatesByTarget = input.targets.map((target) => ({
|
|
709407
|
+
target,
|
|
709408
|
+
spans: findPreparedLiveTrackedTextSpans(input.doc, target)
|
|
709409
|
+
}));
|
|
709410
|
+
for (const { target, spans } of candidatesByTarget) {
|
|
709411
|
+
const span = spans.find((candidate) => !usedSpanIds.has(liveTrackedTextSpanId(candidate)));
|
|
709412
|
+
const alreadyDecided = !span && spans.length === 0 && hasTrackedDecisionLedgerEntry(input.doc, target.rsid);
|
|
709413
|
+
if (!span && !alreadyDecided) {
|
|
709214
709414
|
return { ok: false, failureReason: `tracked decision target ${target.rsid} is not a live tracked text change` };
|
|
709215
709415
|
}
|
|
709216
|
-
|
|
709416
|
+
if (span)
|
|
709417
|
+
usedSpanIds.add(liveTrackedTextSpanId(span));
|
|
709418
|
+
resolved.push({ target, spans: span ? [span] : [] });
|
|
709419
|
+
}
|
|
709420
|
+
for (const { target, spans } of candidatesByTarget) {
|
|
709421
|
+
if (spans.some((span) => !usedSpanIds.has(liveTrackedTextSpanId(span)))) {
|
|
709422
|
+
return {
|
|
709423
|
+
ok: false,
|
|
709424
|
+
failureReason: `tracked decision target ${target.rsid} metadata does not cover every matching live carrier`
|
|
709425
|
+
};
|
|
709426
|
+
}
|
|
709217
709427
|
}
|
|
709218
709428
|
const live = resolved.filter((entry) => entry.spans.length > 0);
|
|
709219
|
-
|
|
709429
|
+
try {
|
|
709430
|
+
const removedCommentCarrierIds = collectCommentCarrierIds(input.removedCommentIds);
|
|
709431
|
+
const work = live.flatMap((entry) => entry.spans.map((span) => {
|
|
709432
|
+
const block = findBlockMap(input.doc, span.blockId)?.block;
|
|
709433
|
+
if (!block)
|
|
709434
|
+
throw new Error(`target block ${span.blockId} is not present in the story shard`);
|
|
709435
|
+
return {
|
|
709436
|
+
target: entry.target,
|
|
709437
|
+
span,
|
|
709438
|
+
block,
|
|
709439
|
+
leftBoundaryAtoms: [],
|
|
709440
|
+
leftBoundaryAnchors: []
|
|
709441
|
+
};
|
|
709442
|
+
}));
|
|
709443
|
+
for (const item of work) {
|
|
709444
|
+
const { target, span, block, leftBoundaryAtoms, leftBoundaryAnchors } = item;
|
|
709445
|
+
const blockLength = getBlockText(block).length;
|
|
709446
|
+
if (span.startOffset < 0 || span.startOffset > blockLength) {
|
|
709447
|
+
throw new Error(`tracked text span ${target.rsid} starts outside block ${span.blockId}`);
|
|
709448
|
+
}
|
|
709449
|
+
if (span.trackedKind === "ins" && input.decision === "reject") {
|
|
709450
|
+
if (span.endOffset < span.startOffset || span.endOffset > blockLength) {
|
|
709451
|
+
throw new Error(`tracked insert span ${target.rsid} is outside block ${span.blockId}`);
|
|
709452
|
+
}
|
|
709453
|
+
}
|
|
709454
|
+
if (span.trackedKind === "del" && input.decision === "reject") {
|
|
709455
|
+
let reachedStart = false;
|
|
709456
|
+
const removedTrackedCarrierIds = trackedTextCarrierIds(span, false);
|
|
709457
|
+
getBlockAtoms(block).forEach((atom) => {
|
|
709458
|
+
if (reachedStart)
|
|
709459
|
+
return;
|
|
709460
|
+
const atomId = String(atom.get(ATOM_KEY.id) ?? "");
|
|
709461
|
+
if (atomId === span.startAtomId) {
|
|
709462
|
+
reachedStart = true;
|
|
709463
|
+
return;
|
|
709464
|
+
}
|
|
709465
|
+
if (atomId && Number(atom.get(ATOM_KEY.visibleOffset) ?? -1) === span.startOffset && Number(atom.get(ATOM_KEY.length) ?? 0) === 0) {
|
|
709466
|
+
if (removedCommentCarrierIds.has(atomId))
|
|
709467
|
+
return;
|
|
709468
|
+
if (removedTrackedCarrierIds.has(atomId)) {
|
|
709469
|
+
throw new Error(`left-boundary atom ${atomId} aliases a removed tracked carrier`);
|
|
709470
|
+
}
|
|
709471
|
+
leftBoundaryAtoms.push(atom);
|
|
709472
|
+
const anchorIdentity2 = rangeAnchorIdentityForAtom(atom);
|
|
709473
|
+
if (anchorIdentity2) {
|
|
709474
|
+
const matchingAnchors = getBlockAnchors(block).toArray().filter((anchor) => anchor.get(ANCHOR_KEY.id) === atom.get(ATOM_KEY.id) && anchor.get(ANCHOR_KEY.kind) === anchorIdentity2.kind && anchor.get(ANCHOR_KEY.boundary) === anchorIdentity2.boundary && Number(anchor.get(ANCHOR_KEY.visibleOffset) ?? -1) === span.startOffset);
|
|
709475
|
+
if (matchingAnchors.length !== 1) {
|
|
709476
|
+
throw new Error(`left-boundary atom ${atomId} does not resolve one exact anchor carrier`);
|
|
709477
|
+
}
|
|
709478
|
+
leftBoundaryAnchors.push(matchingAnchors[0]);
|
|
709479
|
+
}
|
|
709480
|
+
}
|
|
709481
|
+
});
|
|
709482
|
+
if (!reachedStart) {
|
|
709483
|
+
throw new Error(`tracked deletion start ${span.startAtomId} is not present in block ${span.blockId}`);
|
|
709484
|
+
}
|
|
709485
|
+
}
|
|
709486
|
+
}
|
|
709487
|
+
return {
|
|
709488
|
+
ok: true,
|
|
709489
|
+
plan: {
|
|
709490
|
+
doc: input.doc,
|
|
709491
|
+
decision: input.decision,
|
|
709492
|
+
removedCommentCarrierIds,
|
|
709493
|
+
resolved,
|
|
709494
|
+
work
|
|
709495
|
+
}
|
|
709496
|
+
};
|
|
709497
|
+
} catch (error50) {
|
|
709498
|
+
return { ok: false, failureReason: error50 instanceof Error ? error50.message : String(error50) };
|
|
709499
|
+
}
|
|
709500
|
+
}
|
|
709501
|
+
function liveTrackedTextSpanId(span) {
|
|
709502
|
+
return `${span.blockId}\x00${span.startAtomId}\x00${span.endAtomId}`;
|
|
709503
|
+
}
|
|
709504
|
+
function applyPreflightedTrackedTextDecisionsToStory(input) {
|
|
709505
|
+
if (input.plan.work.length === 0)
|
|
709220
709506
|
return { ok: true, applied: false, alreadyDecided: true };
|
|
709221
709507
|
try {
|
|
709222
|
-
resolveStoryShardScope(input.doc).doc.transact(() => {
|
|
709223
|
-
const
|
|
709224
|
-
for (const { target, span } of work) {
|
|
709225
|
-
|
|
709226
|
-
|
|
709227
|
-
|
|
709228
|
-
|
|
709229
|
-
removeCommentCarriersByIds(found, input.removedCommentIds);
|
|
709230
|
-
}
|
|
709231
|
-
const sorted = work.sort((left, right) => {
|
|
709508
|
+
resolveStoryShardScope(input.plan.doc).doc.transact(() => {
|
|
709509
|
+
const { decision, doc: doc2, removedCommentCarrierIds, resolved, work } = input.plan;
|
|
709510
|
+
for (const { target, span, block } of work) {
|
|
709511
|
+
removeTrackedTextCarriers(block, span, decision === "reject" && target.carrierKind === "field-insertion");
|
|
709512
|
+
removeCommentCarriersByIds(block, removedCommentCarrierIds);
|
|
709513
|
+
}
|
|
709514
|
+
const sorted = [...work].sort((left, right) => {
|
|
709232
709515
|
if (left.span.blockId !== right.span.blockId)
|
|
709233
709516
|
return left.span.blockId < right.span.blockId ? -1 : 1;
|
|
709234
709517
|
if (left.span.startOffset !== right.span.startOffset)
|
|
709235
709518
|
return right.span.startOffset - left.span.startOffset;
|
|
709236
|
-
if (left.span.trackedKind === right.span.trackedKind)
|
|
709237
|
-
return
|
|
709519
|
+
if (left.span.trackedKind === right.span.trackedKind) {
|
|
709520
|
+
return right.span.startAtomIndex - left.span.startAtomIndex;
|
|
709521
|
+
}
|
|
709238
709522
|
return left.span.trackedKind === "ins" ? -1 : 1;
|
|
709239
709523
|
});
|
|
709240
|
-
for (const {
|
|
709241
|
-
if (span.trackedKind === "ins" &&
|
|
709524
|
+
for (const { span, leftBoundaryAtoms, leftBoundaryAnchors } of sorted) {
|
|
709525
|
+
if (span.trackedKind === "ins" && decision === "reject") {
|
|
709242
709526
|
const length3 = span.endOffset - span.startOffset;
|
|
709243
|
-
if (length3 < 0) {
|
|
709244
|
-
throw new Error(`tracked insert span ${target.rsid} is outside block ${span.blockId}`);
|
|
709245
|
-
}
|
|
709246
709527
|
if (length3 > 0) {
|
|
709247
709528
|
deleteText2({
|
|
709248
|
-
doc:
|
|
709529
|
+
doc: doc2,
|
|
709249
709530
|
blockId: span.blockId,
|
|
709250
709531
|
offset: span.startOffset,
|
|
709251
709532
|
length: length3,
|
|
@@ -709253,8 +709534,8 @@ function applyTrackedTextDecisionsToStory(input) {
|
|
|
709253
709534
|
});
|
|
709254
709535
|
}
|
|
709255
709536
|
}
|
|
709256
|
-
if (span.trackedKind === "del" &&
|
|
709257
|
-
const found = findBlockMap(
|
|
709537
|
+
if (span.trackedKind === "del" && decision === "reject") {
|
|
709538
|
+
const found = findBlockMap(doc2, span.blockId)?.block;
|
|
709258
709539
|
if (!found)
|
|
709259
709540
|
throw new Error(`target block ${span.blockId} is not present in the story shard`);
|
|
709260
709541
|
let offset = span.startOffset;
|
|
@@ -709266,7 +709547,7 @@ function applyTrackedTextDecisionsToStory(input) {
|
|
|
709266
709547
|
continue;
|
|
709267
709548
|
}
|
|
709268
709549
|
insertText2({
|
|
709269
|
-
doc:
|
|
709550
|
+
doc: doc2,
|
|
709270
709551
|
blockId: span.blockId,
|
|
709271
709552
|
offset,
|
|
709272
709553
|
text: segment.text,
|
|
@@ -709293,10 +709574,12 @@ function applyTrackedTextDecisionsToStory(input) {
|
|
|
709293
709574
|
if (restoredBreakXml) {
|
|
709294
709575
|
throw new Error(`attributed break restoration in ${span.blockId} is incomplete`);
|
|
709295
709576
|
}
|
|
709577
|
+
leftBoundaryAtoms.forEach((atom) => atom.set(ATOM_KEY.visibleOffset, span.startOffset));
|
|
709578
|
+
leftBoundaryAnchors.forEach((anchor) => anchor.set(ANCHOR_KEY.visibleOffset, span.startOffset));
|
|
709296
709579
|
}
|
|
709297
709580
|
}
|
|
709298
709581
|
for (const { target } of resolved) {
|
|
709299
|
-
recordTrackedDecision(
|
|
709582
|
+
recordTrackedDecision(doc2, target.rsid, decision, input.txId);
|
|
709300
709583
|
}
|
|
709301
709584
|
}, STORY_SURFACE_BACKEND_ORIGIN);
|
|
709302
709585
|
} catch (error50) {
|
|
@@ -709375,6 +709658,7 @@ function collectLiveTrackedTextSpansInBlock(block, rsid, trackedKind) {
|
|
|
709375
709658
|
blockId,
|
|
709376
709659
|
startOffset: start.offset,
|
|
709377
709660
|
endOffset: trackedKind === "del" ? start.offset + deletedTextLength2 : end.offset,
|
|
709661
|
+
startAtomIndex: start.index,
|
|
709378
709662
|
startAtomId: start.id,
|
|
709379
709663
|
endAtomId: end.id,
|
|
709380
709664
|
preservedAtomIds: preservedForSpan.map((atom) => atom.id),
|
|
@@ -709386,24 +709670,38 @@ function collectLiveTrackedTextSpansInBlock(block, rsid, trackedKind) {
|
|
|
709386
709670
|
return spans;
|
|
709387
709671
|
}
|
|
709388
709672
|
function removeTrackedTextCarriers(block, span, removeContainedAtoms) {
|
|
709389
|
-
const ids =
|
|
709673
|
+
const ids = trackedTextCarrierIds(span, removeContainedAtoms);
|
|
709674
|
+
deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
|
|
709675
|
+
deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
|
|
709676
|
+
}
|
|
709677
|
+
function trackedTextCarrierIds(span, includeContainedAtoms) {
|
|
709678
|
+
return new Set([
|
|
709390
709679
|
span.startAtomId,
|
|
709391
709680
|
span.endAtomId,
|
|
709392
709681
|
...span.preservedAtomIds,
|
|
709393
|
-
...
|
|
709682
|
+
...includeContainedAtoms ? span.containedAtomIds : []
|
|
709394
709683
|
]);
|
|
709395
|
-
deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
|
|
709396
|
-
deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
|
|
709397
709684
|
}
|
|
709398
|
-
function
|
|
709399
|
-
|
|
709400
|
-
|
|
709685
|
+
function rangeAnchorIdentityForAtom(atom) {
|
|
709686
|
+
const atomKind = atom.get(ATOM_KEY.kind);
|
|
709687
|
+
if (atomKind !== INLINE_ATOM_KIND.commentMarker && atomKind !== INLINE_ATOM_KIND.bookmark)
|
|
709688
|
+
return null;
|
|
709689
|
+
const marker = String(asRecord6(atom.get(ATOM_KEY.meta)).marker ?? "");
|
|
709690
|
+
const boundary = marker.endsWith("End") ? "end" : marker.endsWith("Start") ? "start" : "point";
|
|
709691
|
+
return { kind: atomKind === INLINE_ATOM_KIND.commentMarker ? "comment" : "bookmark", boundary };
|
|
709692
|
+
}
|
|
709693
|
+
function collectCommentCarrierIds(commentIds) {
|
|
709401
709694
|
const ids = new Set;
|
|
709402
709695
|
for (const commentId of commentIds) {
|
|
709403
709696
|
ids.add(`comment:${commentId}:start`);
|
|
709404
709697
|
ids.add(`comment:${commentId}:end`);
|
|
709405
709698
|
ids.add(`comment:${commentId}:ref`);
|
|
709406
709699
|
}
|
|
709700
|
+
return ids;
|
|
709701
|
+
}
|
|
709702
|
+
function removeCommentCarriersByIds(block, ids) {
|
|
709703
|
+
if (ids.size === 0)
|
|
709704
|
+
return;
|
|
709407
709705
|
deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
|
|
709408
709706
|
deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
|
|
709409
709707
|
}
|
|
@@ -709509,11 +709807,14 @@ function admitPreparedStorySurfaceMutation(prepared, options) {
|
|
|
709509
709807
|
return options.session && extension2.family === "storyBlocks" && extension2.contentControlRewrite && storyIds.length === 1 ? { ok: true } : { ok: false, message: "Content-control rewrite requires a prepared structural delta and owning session." };
|
|
709510
709808
|
}
|
|
709511
709809
|
if (extension2.family === "storyTrackedDecide") {
|
|
709512
|
-
if (usesTrackedDecisionSessionSync(prepared, extension2)) {
|
|
709810
|
+
if (usesTrackedDecisionSessionSync(prepared, extension2, options)) {
|
|
709513
709811
|
return options.session ? { ok: true } : { ok: false, message: "tracked-change decision session sync requires an authoritative session" };
|
|
709514
709812
|
}
|
|
709515
709813
|
const trackedDecision = validatePreparedTrackedDecide(prepared, extension2, options);
|
|
709516
|
-
|
|
709814
|
+
if (!trackedDecision.ok)
|
|
709815
|
+
return { ok: false, message: trackedDecision.failureReason };
|
|
709816
|
+
const preflight2 = preflightPreparedTrackedDecide({ prepared, ...trackedDecision });
|
|
709817
|
+
return preflight2.ok ? { ok: true, trackedDecision: preflight2.preflight } : { ok: false, message: preflight2.failureReason };
|
|
709517
709818
|
}
|
|
709518
709819
|
if (extension2.family === "storyTable") {
|
|
709519
709820
|
if (extension2.historyReplay) {
|
|
@@ -709584,14 +709885,28 @@ function touchesOwnedStoryPart(prepared) {
|
|
|
709584
709885
|
const touchedParts = new Set(prepared.resolvedTargets.partUris.map((partUri) => String(partUri)));
|
|
709585
709886
|
return prepared.resolvedTargets.storyPartOwnership.some((entry) => touchedParts.has(String(entry.partUri)));
|
|
709586
709887
|
}
|
|
709587
|
-
function usesTrackedDecisionSessionSync(prepared, extension2) {
|
|
709888
|
+
function usesTrackedDecisionSessionSync(prepared, extension2, options) {
|
|
709588
709889
|
if (extension2.historyReplay || extension2.sessionSync)
|
|
709589
709890
|
return true;
|
|
709590
709891
|
if (hasPreparedCommentRefRemaps(prepared))
|
|
709591
709892
|
return true;
|
|
709592
|
-
if (extension2.trackedTextDecide
|
|
709593
|
-
|
|
709594
|
-
|
|
709893
|
+
if (!extension2.trackedTextDecide) {
|
|
709894
|
+
if (prepared.source.kind !== "trackedChangeDecide")
|
|
709895
|
+
return false;
|
|
709896
|
+
return prepared.source.targets.some((target) => target.formatting !== undefined || target.structural !== undefined || target.derivedStructural !== undefined);
|
|
709897
|
+
}
|
|
709898
|
+
return extension2.trackedTextDecide.targets.some((target) => {
|
|
709899
|
+
const doc2 = options.resolveStoryShard(target.storyId);
|
|
709900
|
+
if (!doc2)
|
|
709901
|
+
return false;
|
|
709902
|
+
const liveSpans = collectLiveTrackedTextSpans(doc2, target.rsid, target.trackedKind, [target.blockId]);
|
|
709903
|
+
if (liveSpans.length > 1)
|
|
709904
|
+
return true;
|
|
709905
|
+
if (!hasTrackedDecisionLedgerEntry(doc2, target.rsid) || findPreparedLiveTrackedTextSpans(doc2, target).length > 0) {
|
|
709906
|
+
return false;
|
|
709907
|
+
}
|
|
709908
|
+
return liveSpans.length > 0;
|
|
709909
|
+
});
|
|
709595
709910
|
}
|
|
709596
709911
|
function tryMirrorStoryText(prepared, extension2, options, admitted) {
|
|
709597
709912
|
const validation = admitted ?? validateDirectStoryText(prepared, extension2, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/mcp",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.9",
|
|
4
4
|
"description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
27
|
-
"@superdoc/sdk": "2.13.0-next.
|
|
27
|
+
"@superdoc/sdk": "2.13.0-next.11",
|
|
28
28
|
"debug": "^4.4.3",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"superdoc": "2.16.0-next.
|
|
33
|
-
"@superdoc/docx-engine": "0.15.0-next.
|
|
32
|
+
"superdoc": "2.16.0-next.9",
|
|
33
|
+
"@superdoc/docx-engine": "0.15.0-next.9",
|
|
34
34
|
"@superdoc/document-api": "0.1.0-alpha.0",
|
|
35
35
|
"@types/bun": "^1.3.8",
|
|
36
36
|
"@types/node": "22.19.2",
|