@superdoc/mcp 1.0.1-next.6 → 1.0.1-next.8

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.
Files changed (2) hide show
  1. package/dist/index.js +168 -19
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31314,7 +31314,7 @@ var init_host = __esm(() => {
31314
31314
  });
31315
31315
 
31316
31316
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31317
- var SDK_VERSION = "2.13.1-next.6";
31317
+ var SDK_VERSION = "2.13.1-next.8";
31318
31318
 
31319
31319
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31320
31320
  import { chmodSync, existsSync } from "node:fs";
@@ -193399,9 +193399,10 @@ function runInsertInlineControlCommit(input) {
193399
193399
  preconditions,
193400
193400
  patchMaps,
193401
193401
  textRangeShifts: shifts,
193402
- ...changeMode === "direct" && op.control === "lineBreak" && "runPropertiesXml" in rewritten ? {
193403
- directLineBreak: {
193404
- kind: "directLineBreak",
193402
+ ...changeMode === "direct" && (op.control === "tab" || op.control === "lineBreak") && "runPropertiesXml" in rewritten ? {
193403
+ directInlineControl: {
193404
+ kind: "directInlineControl",
193405
+ control: op.control,
193405
193406
  afterParagraphTail: "afterParagraphTail" in rewritten && rewritten.afterParagraphTail === true,
193406
193407
  blockId: op.on.startBlockId,
193407
193408
  startOffset: op.on.startOffset,
@@ -193708,7 +193709,7 @@ function finalizeInlineControlCommit(args) {
193708
193709
  changeMode: op.changeMode ?? "direct",
193709
193710
  targetBlockIds: [op.on.startBlockId],
193710
193711
  atomCarrierContract: SD_DEFAULT_ATOM_CARRIER_CONTRACT,
193711
- ...args.directLineBreak ? { directLineBreak: args.directLineBreak } : {},
193712
+ ...args.directInlineControl ? { directInlineControl: args.directInlineControl } : {},
193712
193713
  ...args.trackedTextInsert ? { trackedTextInsert: args.trackedTextInsert } : {},
193713
193714
  ...args.trackedTextEdit ? { trackedTextEdit: args.trackedTextEdit } : {}
193714
193715
  };
@@ -369135,6 +369136,7 @@ async function compilePlan(context, input) {
369135
369136
  }
369136
369137
  detectTargetConflicts(context, steps, failures);
369137
369138
  detectUnsupportedRuntimeDrift(input.steps, failures);
369139
+ detectTargetOffsetDriftRisk(steps, failures);
369138
369140
  return { evaluatedRevision, steps, failures };
369139
369141
  }
369140
369142
  function isOrderedAtomicTextProgram(steps) {
@@ -369619,6 +369621,14 @@ function detectUnsupportedRuntimeDrift(steps, failures) {
369619
369621
  message: "multi-step mutation plans cannot use revision-bound ref targets; use selector targets so the engine can re-resolve each step before commit."
369620
369622
  });
369621
369623
  }
369624
+ if (step3.where.by === "target" && step3.where.target.kind === "selection" && step3.where.target.start.kind === "text" && step3.where.target.end.kind === "text" && step3.where.target.start.blockId !== step3.where.target.end.blockId) {
369625
+ failures.push({
369626
+ code: "CAPABILITY_UNSUPPORTED",
369627
+ stepId: step3.id,
369628
+ phase: "compile",
369629
+ message: 'multi-step mutation plans cannot combine a cross-block by:"target" step with other mutating steps; ' + "conflict and offset-drift detection only see that step's first block. Apply it alone, or split the " + "plan so the cross-block step runs in its own mutations.apply call."
369630
+ });
369631
+ }
369622
369632
  }
369623
369633
  }
369624
369634
  }
@@ -369659,6 +369669,33 @@ function detectTargetConflicts(context, steps, failures) {
369659
369669
  }
369660
369670
  }
369661
369671
  }
369672
+ function detectTargetOffsetDriftRisk(steps, failures) {
369673
+ const textShiftingOps = new Set(["text.rewrite", "text.delete", "text.insert"]);
369674
+ const byBlock = new Map;
369675
+ for (const step3 of steps) {
369676
+ if (!textShiftingOps.has(step3.op) || step3.source.op === "assert" || step3.source.where?.by !== "target")
369677
+ continue;
369678
+ const resolutions = step3.resolutions ?? (step3.resolution ? [step3.resolution] : []);
369679
+ for (const resolution of resolutions) {
369680
+ const key2 = `${storyKeyForTarget(resolution.target)}::${resolution.target.blockId}`;
369681
+ const list2 = byBlock.get(key2) ?? [];
369682
+ list2.push(step3);
369683
+ byBlock.set(key2, list2);
369684
+ }
369685
+ }
369686
+ for (const blockSteps of byBlock.values()) {
369687
+ if (blockSteps.length <= 1)
369688
+ continue;
369689
+ for (const step3 of blockSteps) {
369690
+ failures.push({
369691
+ code: "CAPABILITY_UNSUPPORTED",
369692
+ stepId: step3.stepId,
369693
+ phase: "compile",
369694
+ message: `step "${step3.stepId}" shares a block with another by:"target" text-shifting step in this plan; explicit ` + "offsets are not re-derived between steps, so an earlier same-block step can shift this one's offsets. " + 'Split same-block edits into separate mutations.apply calls, or use by:"select" for later occurrences in ' + "the same block."
369695
+ });
369696
+ }
369697
+ }
369698
+ }
369662
369699
  function conflictRangeForResolution(context, step3, resolution) {
369663
369700
  if (step3.source.op !== "format.apply" || step3.source.args.scope !== "block" && step3.source.args.alignment === undefined) {
369664
369701
  return resolution.range;
@@ -369713,9 +369750,117 @@ async function resolveMutationStep(context, step3, story, changeMode) {
369713
369750
  const compiled = resolveRefMutationStep(context, step3, story, matches[0].ref);
369714
369751
  return applySelectMatchReplacementPolicy(compiled, step3, matches[0].groups);
369715
369752
  }
369753
+ if (step3.where.by === "target") {
369754
+ return resolveTargetWhereMutationStep(context, step3, step3.where, story, changeMode);
369755
+ }
369716
369756
  const ref5 = resolveStepRef(step3);
369717
369757
  return resolveRefMutationStep(context, step3, story, ref5);
369718
369758
  }
369759
+ function resolveTargetWhereMutationStep(context, step3, where, story, changeMode) {
369760
+ const target = where.target;
369761
+ if (target.kind !== "selection" || target.start.kind !== "text" || target.end.kind !== "text") {
369762
+ throw new DocumentApiValidationError2("INVALID_TARGET", `v2 ${step3.op} target steps require a text SelectionTarget with text-kind endpoints.`);
369763
+ }
369764
+ const storyLocator = target.story ?? story;
369765
+ if (!isSupportedMutationStoryScope(storyLocator)) {
369766
+ throw new DocumentApiValidationError2("CAPABILITY_UNSUPPORTED", `v2 mutation plan engine supports only the body story; "${storyLocator?.storyType}" story targets are not supported.`);
369767
+ }
369768
+ if (step3.op === "text.rewrite" && step3.args.replacementMode === "regex-template") {
369769
+ throw new DocumentApiValidationError2("CAPABILITY_UNSUPPORTED", 'v2 text.rewrite target steps do not support replacementMode "regex-template"; an explicit target carries no ' + 'capture groups. Use a by:"select" step for regex-template replacements.');
369770
+ }
369771
+ const selectionMutation = new V2SelectionMutationAdapter(context);
369772
+ if (step3.op === "text.insert") {
369773
+ const { text: text4, position: position2 } = readInsertArgs(step3);
369774
+ const point3 = position2 === "before" ? target.start : target.end;
369775
+ const collapsed = {
369776
+ kind: "selection",
369777
+ start: point3,
369778
+ end: point3,
369779
+ ...target.story ? { story: target.story } : {},
369780
+ ...target.coordinateSpace ? { coordinateSpace: target.coordinateSpace } : {}
369781
+ };
369782
+ const request = { kind: "insert", target: collapsed, text: text4, ...story ? { in: story } : {} };
369783
+ const receipt3 = selectionMutation.execute({ kind: "insert", target: collapsed, text: text4, ...story ? { in: story } : {} }, { changeMode, dryRun: true });
369784
+ if (!receipt3.success)
369785
+ throw new DocumentApiValidationError2(receipt3.failure.code, receipt3.failure.message);
369786
+ const resolution2 = {
369787
+ target: receipt3.resolution.target,
369788
+ range: receipt3.resolution.range,
369789
+ text: receipt3.resolution.text
369790
+ };
369791
+ return {
369792
+ stepId: step3.id,
369793
+ op: "text.insert",
369794
+ resolution: resolution2,
369795
+ request,
369796
+ noopEquivalentText: text4.length === 0 ? text4 : undefined,
369797
+ source: step3
369798
+ };
369799
+ }
369800
+ if (step3.op === "format.apply") {
369801
+ const crossBlock = target.start.blockId !== target.end.blockId;
369802
+ if (crossBlock && (step3.args.alignment !== undefined || step3.args.scope === "block")) {
369803
+ throw new DocumentApiValidationError2("CAPABILITY_UNSUPPORTED", "v2 format.apply target steps spanning more than one block support only an inline patch with the default " + '(non-block) scope; split a cross-block alignment or scope:"block" edit into one step per block.');
369804
+ }
369805
+ const placeholderResolution = {
369806
+ target: {
369807
+ kind: "text",
369808
+ blockId: target.start.blockId,
369809
+ range: { start: 0, end: 0 },
369810
+ ...storyLocator ? { story: storyLocator } : {}
369811
+ },
369812
+ range: { from: 0, to: 0 },
369813
+ text: ""
369814
+ };
369815
+ const request = buildFormatCommitRequest(context, step3, placeholderResolution, target, story, storyLocator);
369816
+ if (request.kind !== "format") {
369817
+ throw new DocumentApiValidationError2("INVALID_TARGET", "v2 format.apply target steps require a resolvable target.");
369818
+ }
369819
+ let resolution2;
369820
+ if (request.inline) {
369821
+ const receipt3 = "target" in request ? selectionMutation.execute({ kind: "format", target: request.target, inline: request.inline, ...request.in ? { in: request.in } : {} }, { changeMode, dryRun: true, ...request.skipAtomicObjects ? { skipAtomicObjects: true } : {} }) : selectionMutation.execute({ kind: "format", ref: request.ref, inline: request.inline, ...request.in ? { in: request.in } : {} }, { changeMode, dryRun: true, ...request.skipAtomicObjects ? { skipAtomicObjects: true } : {} });
369822
+ if (!receipt3.success)
369823
+ throw new DocumentApiValidationError2(receipt3.failure.code, receipt3.failure.message);
369824
+ resolution2 = {
369825
+ target: receipt3.resolution.target,
369826
+ range: receipt3.resolution.range,
369827
+ text: receipt3.resolution.text
369828
+ };
369829
+ } else {
369830
+ const blockText = readBlockTargetText(context, target.start.blockId, Number.MAX_SAFE_INTEGER, storyLocator, target.coordinateSpace);
369831
+ resolution2 = {
369832
+ target: { kind: "text", blockId: target.start.blockId, range: { start: 0, end: blockText.length }, ...storyLocator ? { story: storyLocator } : {} },
369833
+ range: { from: 0, to: blockText.length },
369834
+ text: blockText
369835
+ };
369836
+ }
369837
+ return {
369838
+ stepId: step3.id,
369839
+ op: "format.apply",
369840
+ resolution: resolution2,
369841
+ request,
369842
+ source: step3
369843
+ };
369844
+ }
369845
+ const rewriteTemplate = step3.op === "text.delete" ? "" : normalizeReplacement(step3.args.replacement);
369846
+ const probeReceipt = selectionMutation.execute({ kind: "replace", target, text: rewriteTemplate, ...story ? { in: story } : {} }, { changeMode, dryRun: true });
369847
+ if (!probeReceipt.success)
369848
+ throw new DocumentApiValidationError2(probeReceipt.failure.code, probeReceipt.failure.message);
369849
+ const resolution = {
369850
+ target: probeReceipt.resolution.target,
369851
+ range: probeReceipt.resolution.range,
369852
+ text: probeReceipt.resolution.text
369853
+ };
369854
+ const replacementText = step3.op === "text.delete" ? "" : replacementTextForMatch(step3, resolution.text);
369855
+ return {
369856
+ stepId: step3.id,
369857
+ op: step3.op,
369858
+ resolution,
369859
+ request: { kind: "replace", target, text: replacementText, ...story ? { in: story } : {} },
369860
+ ...step3.op === "text.rewrite" ? { noopEquivalentText: replacementText } : {},
369861
+ source: step3
369862
+ };
369863
+ }
369719
369864
  function resolveRefMutationStep(context, step3, story, ref5, cache) {
369720
369865
  if (isV2RangeRef(ref5)) {
369721
369866
  return resolveRangeRefMutationStep(context, step3, story, ref5);
@@ -424205,8 +424350,12 @@ function tryMirrorStoryText(prepared, extension2, options, admitted) {
424205
424350
  const validation = admitted ?? validateDirectStoryText(prepared, extension2, options);
424206
424351
  if (!validation.ok)
424207
424352
  return { mirrored: false, failureReason: validation.failureReason };
424208
- const source = validation.source.kind === "insertInlineControl" ? { changeMode: "direct", on: validation.source.on, newText: `
424209
- ` } : validation.source;
424353
+ const source = validation.source.kind === "insertInlineControl" ? {
424354
+ changeMode: "direct",
424355
+ on: validation.source.on,
424356
+ newText: validation.inlineControl?.control === "tab" ? "\t" : `
424357
+ `
424358
+ } : validation.source;
424210
424359
  const target = validation.target;
424211
424360
  try {
424212
424361
  target.scope.doc.transact(() => {
@@ -424275,7 +424424,7 @@ function tryMirrorStoryText(prepared, extension2, options, admitted) {
424275
424424
  });
424276
424425
  }
424277
424426
  if (source.newText.length > 0) {
424278
- if (deleteLength === 0 || validation.lineBreak) {
424427
+ if (deleteLength === 0 || validation.inlineControl) {
424279
424428
  if (!validation.directInsert) {
424280
424429
  throw new Error("direct storyText mirror missing typed insert metadata");
424281
424430
  }
@@ -424285,7 +424434,7 @@ function tryMirrorStoryText(prepared, extension2, options, admitted) {
424285
424434
  text: source.newText,
424286
424435
  txId: prepared.txId,
424287
424436
  directInsert: validation.directInsert,
424288
- preserveZeroLengthAtOffset: validation.lineBreak?.afterParagraphTail,
424437
+ preserveZeroLengthAtOffset: validation.inlineControl?.afterParagraphTail,
424289
424438
  acceptedTextInsertionSplit: validation.acceptedTextInsertionSplit
424290
424439
  });
424291
424440
  } else {
@@ -424405,10 +424554,10 @@ function cloneTrackedWrapperAtom(source, id2, visibleOffset) {
424405
424554
  }
424406
424555
  function validateDirectStoryText(prepared, extension2, options) {
424407
424556
  const source = prepared.source;
424408
- const lineBreak = source.kind === "insertInlineControl" ? extension2.directLineBreak : undefined;
424557
+ const inlineControl = source.kind === "insertInlineControl" ? extension2.directInlineControl : undefined;
424409
424558
  if (source.kind === "insertInlineControl") {
424410
- if (source.control !== "lineBreak" || (source.changeMode ?? "direct") !== "direct" || !lineBreak || lineBreak.kind !== "directLineBreak" || typeof lineBreak.afterParagraphTail !== "boolean" || lineBreak.blockId !== source.on.startBlockId || lineBreak.startOffset !== source.on.startOffset || lineBreak.endOffset !== source.on.endOffset || parsePreparedRunAttributes(lineBreak.runPropertiesXml) === null) {
424411
- return { ok: false, failureReason: "storyText requires matching direct line-break metadata" };
424559
+ if (source.control !== "tab" && source.control !== "lineBreak" || (source.changeMode ?? "direct") !== "direct" || !inlineControl || inlineControl.kind !== "directInlineControl" || inlineControl.control !== source.control || typeof inlineControl.afterParagraphTail !== "boolean" || inlineControl.blockId !== source.on.startBlockId || inlineControl.startOffset !== source.on.startOffset || inlineControl.endOffset !== source.on.endOffset || parsePreparedRunAttributes(inlineControl.runPropertiesXml) === null) {
424560
+ return { ok: false, failureReason: "storyText requires matching direct inline-control metadata" };
424412
424561
  }
424413
424562
  }
424414
424563
  if (source.kind !== "editText" && source.kind !== "insertInlineControl") {
@@ -424456,15 +424605,15 @@ function validateDirectStoryText(prepared, extension2, options) {
424456
424605
  if (trackedEdit && !trackedEdit.ok) {
424457
424606
  return { ok: false, failureReason: trackedEdit.failureReason };
424458
424607
  }
424459
- const directInsert = lineBreak ? {
424608
+ const directInsert = inlineControl ? {
424460
424609
  ok: true,
424461
424610
  directInsert: {
424462
424611
  kind: "directTextInsert",
424463
- blockId: lineBreak.blockId,
424464
- startOffset: lineBreak.startOffset,
424465
- text: `
424612
+ blockId: inlineControl.blockId,
424613
+ startOffset: inlineControl.startOffset,
424614
+ text: inlineControl.control === "tab" ? "\t" : `
424466
424615
  `,
424467
- runPropertiesXml: lineBreak.runPropertiesXml
424616
+ runPropertiesXml: inlineControl.runPropertiesXml
424468
424617
  }
424469
424618
  } : source.kind === "editText" && source.changeMode === "direct" && isPureDirectTextInsert(source) ? validateDirectTextInsert(source, extension2) : null;
424470
424619
  if (directInsert && !directInsert.ok) {
@@ -424502,7 +424651,7 @@ function validateDirectStoryText(prepared, extension2, options) {
424502
424651
  };
424503
424652
  }
424504
424653
  const target = resolveStoryTextMutationTarget(doc2, source.on.startBlockId);
424505
- if (lineBreak && !lineBreak.afterParagraphTail && hasStoryTextBoundaryInRange(target, source.on.startOffset, source.on.endOffset)) {
424654
+ if (inlineControl?.control === "lineBreak" && !inlineControl.afterParagraphTail && hasStoryTextBoundaryInRange(target, source.on.startOffset, source.on.endOffset)) {
424506
424655
  return { ok: false, failureReason: "line-break boundary placement requires typed collaboration support" };
424507
424656
  }
424508
424657
  let validatedTrackedRefinement;
@@ -424535,7 +424684,7 @@ function validateDirectStoryText(prepared, extension2, options) {
424535
424684
  target,
424536
424685
  ...acceptedTextInsertionSplit ? { acceptedTextInsertionSplit } : {},
424537
424686
  ...directInsert?.ok ? { directInsert: directInsert.directInsert } : {},
424538
- ...lineBreak ? { lineBreak: { afterParagraphTail: lineBreak.afterParagraphTail } } : {},
424687
+ ...inlineControl ? { inlineControl: { control: inlineControl.control, afterParagraphTail: inlineControl.afterParagraphTail } } : {},
424539
424688
  ...trackedInsert?.ok ? { trackedInsert: trackedInsert.trackedInsert } : {},
424540
424689
  ...trackedInsertContinuation ? { trackedInsertContinuation: true } : {},
424541
424690
  ...validatedTrackedRefinement ? { trackedRefinement: validatedTrackedRefinement } : {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/mcp",
3
- "version": "1.0.1-next.6",
3
+ "version": "1.0.1-next.8",
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.1-next.6",
27
+ "@superdoc/sdk": "2.13.1-next.8",
28
28
  "debug": "^4.4.3",
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "superdoc": "2.16.1-next.6",
33
- "@superdoc/docx-engine": "0.15.1-next.5",
32
+ "superdoc": "2.16.1-next.8",
33
+ "@superdoc/docx-engine": "0.15.1-next.8",
34
34
  "@superdoc/document-api": "0.1.0-alpha.0",
35
35
  "@types/bun": "^1.3.8",
36
36
  "@types/node": "22.19.2",