@wordinweb/agent 0.1.0 → 0.2.0

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.d.ts CHANGED
@@ -121,10 +121,21 @@ interface RunProps {
121
121
  raise?: number;
122
122
  /** w:outline — hollow stroked glyphs. */
123
123
  outline?: boolean;
124
+ /** w14:textOutline — glyph outline stroke (WordArt gallery styles). */
125
+ textOutline?: {
126
+ color: string;
127
+ width: number;
128
+ };
129
+ /** w:shadow / w14:shadow — offset glyph shadow. */
130
+ textShadow?: boolean;
124
131
  /** w:emboss / w:imprint — Word triple-draws offset copies. */
125
132
  emboss?: boolean;
126
133
  imprint?: boolean;
127
134
  vanish?: boolean;
135
+ /** w:rPr w:snapToGrid: whether this run participates in the section's
136
+ * docGrid. A line whose runs ALL declare 0 lays off the grid (see
137
+ * finishLine); ParaProps.snapToGrid covers the whole paragraph. */
138
+ snapToGrid?: boolean;
128
139
  /** Character style id (w:rStyle). */
129
140
  styleId?: string;
130
141
  lang?: string;
@@ -306,7 +317,7 @@ interface EmbeddedObjectReference {
306
317
  progId: string;
307
318
  }
308
319
  /** OMML equation node (subset: runs, scripts, fractions, radicals). */
309
- type MathNode = {
320
+ type MathNode = ({
310
321
  t: "run";
311
322
  text: string;
312
323
  normal?: boolean;
@@ -375,6 +386,15 @@ type MathNode = {
375
386
  pos: "low" | "upp";
376
387
  e: MathNode[];
377
388
  lim: MathNode[];
389
+ }) & {
390
+ /**
391
+ * The OMML element this node was read from. Only the math EDITOR's reader
392
+ * (edit/math.ts) sets it; the renderer's parser leaves it undefined. Editing
393
+ * re-emits through it, so the properties the linear syntax does not spell
394
+ * out — run fonts, m:ctrlPr, a matrix's column specs, an n-ary's limit
395
+ * placement — survive a text edit instead of being dropped.
396
+ */
397
+ src?: XmlElement;
378
398
  };
379
399
  interface MathContent {
380
400
  kind: "math";
@@ -403,6 +423,11 @@ interface FieldContent {
403
423
  * (in the fldChar begin's w:ffData). Its presence makes the rendered ballot
404
424
  * box a click-to-toggle target; the glyph derives from its w:checked child. */
405
425
  checkbox?: XmlElement;
426
+ /** The field's own XML: the `w:fldSimple`, or the `w:fldChar` begin of a
427
+ * complex field. The update pass (edit/update-fields.ts) writes a recomputed
428
+ * result back through it — layout resolves fields from this model, so
429
+ * without the link the computed value has nowhere to land in the file. */
430
+ src?: XmlElement;
406
431
  }
407
432
  /** What an anchored shape's coordinates are measured from. "char" (relH=
408
433
  * "character") measures from the anchor run's pen position; "line" (relV=
@@ -478,12 +503,18 @@ interface ShapeTextbox {
478
503
  r: number;
479
504
  b: number;
480
505
  };
481
- /** Non-rect preset geometry: paint this outline (in a viewW x viewH space
482
- * scaled to the shape box) instead of a rectangle. */
506
+ /** Non-rect preset geometry: paint these outline paths (in a viewW x viewH
507
+ * space scaled to the shape box) instead of a rectangle. Each path carries
508
+ * its resolved fill colour (undefined = unfilled) and whether the shape's
509
+ * stroke applies to it. */
483
510
  geom?: {
484
- d: string;
485
511
  viewW: number;
486
512
  viewH: number;
513
+ paths: {
514
+ d: string;
515
+ fill?: string;
516
+ stroke: boolean;
517
+ }[];
487
518
  };
488
519
  /** bodyPr a:noAutofit: the box does NOT grow with its text — Word hides
489
520
  * whole lines that stick out past the shape bottom (phase23 p12 ovals:
@@ -493,6 +524,13 @@ interface ShapeTextbox {
493
524
  * plus the top/bottom insets (the stored cy is only Word's last cached
494
525
  * value). Width is fixed. */
495
526
  autofitHeight?: boolean;
527
+ /** bodyPr a:normAutofit — "shrink text on overflow". The mode is recorded
528
+ * because the fit report names it, NOT because it changes the layout:
529
+ * probe-shapefit measured fourteen normAutofit shapes through desktop Word
530
+ * and every one paints at its authored size and clips at the box bottom,
531
+ * exactly like a:noAutofit. `clipText` is set alongside this and is what the
532
+ * layout reads. */
533
+ shrinkText?: boolean;
496
534
  /** Linked text-box chain id (wps:txbx/@id or wps:linkedTxbx/@id): boxes with
497
535
  * the same id form one story. The seq-0 box (wps:txbx) holds the content;
498
536
  * later boxes (wps:linkedTxbx, chainSeq>0) are empty sinks that continue the
@@ -569,6 +607,16 @@ interface ShapeArt {
569
607
  behind?: boolean;
570
608
  /** a:xfrm rotation, degrees clockwise. */
571
609
  rotation?: number;
610
+ /** wp:wrapSquare/.../wrapTopAndBottom on the anchor. Only FRAME stories
611
+ * (header/footer/cell) act on it - body flow ignores art wrap, as before. */
612
+ wrap?: WrapMode;
613
+ /** wp:anchor dist* in px, used with `wrap`. */
614
+ dist?: {
615
+ t: number;
616
+ b: number;
617
+ l: number;
618
+ r: number;
619
+ };
572
620
  lines: DrawingLine[];
573
621
  images: DrawingImage[];
574
622
  paths: DrawingPath[];
@@ -702,16 +750,91 @@ interface DrawingContent {
702
750
  * SmartArt cached-drawing shapes). Painted above lines/paths. */
703
751
  texts?: DrawingTextShape[];
704
752
  }
705
- type ChartType = "column" | "bar" | "line" | "pie";
753
+ /** The c:chartSpace plot kinds the renderer paints. Anything else (3-D, radar,
754
+ * surface, stock, bubble) parses with `unsupported` set instead. */
755
+ type ChartType = "column" | "bar" | "line" | "pie" | "doughnut" | "area" | "scatter";
706
756
  interface ChartSeries {
707
757
  name: string;
708
758
  values: number[];
759
+ /** c:xVal of a scatter series. Every other type shares one category axis,
760
+ * so only scatter carries per-series x values. */
761
+ xValues?: number[];
762
+ /** Explicit series fill/line from c:spPr, overriding the palette slot. */
763
+ color?: string;
764
+ /** Explicit c:dPt fills, keyed by point index (pie slices, single bars). */
765
+ pointColors?: Record<number, string>;
766
+ /** c:smooth — draw the line series through a spline instead of segments. */
767
+ smooth?: boolean;
768
+ /** c:spPr/a:ln/@w, in px. A line or scatter series says here how heavy its
769
+ * stroke is; a scatter series, whose stroke is optional, says it has one. */
770
+ lineWidth?: number;
771
+ /** c:marker/c:symbol, an ST_MarkerStyle name. "none" draws no marker, and a
772
+ * name with no shape behind it takes the series' slot in Word's sequence. */
773
+ markerSymbol?: string;
774
+ /** c:marker/c:size, the width across the marker in px. */
775
+ markerSize?: number;
776
+ }
777
+ type ChartTickMark = "none" | "in" | "out" | "cross";
778
+ /** One axis of a 2-D chart (c:catAx/c:valAx/c:dateAx). */
779
+ interface ChartAxis {
780
+ /** c:delete val="1": Word draws no line, ticks or labels for the axis. */
781
+ hidden?: boolean;
782
+ /** A c:majorGridlines child is present. */
783
+ gridlines?: boolean;
784
+ /** c:numFmt formatCode applied to the tick labels, e.g. "0.0%". */
785
+ format?: string;
786
+ title?: string;
787
+ /** c:scaling overrides of the automatic scale. */
788
+ min?: number;
789
+ max?: number;
790
+ majorUnit?: number;
791
+ /** c:scaling/c:orientation val="maxMin". */
792
+ reversed?: boolean;
793
+ /** c:majorTickMark / c:minorTickMark. The schema default is "out" for major
794
+ * and "none" for minor; Word writes both explicitly. */
795
+ majorTick?: ChartTickMark;
796
+ minorTick?: ChartTickMark;
797
+ /** c:tickLblPos val="none" keeps the axis but drops its labels. */
798
+ labels?: boolean;
799
+ /** c:crossBetween on a value axis, which decides where the category axis puts
800
+ * its points: "between" insets them by half a category (Word's choice for
801
+ * bar and column), "midCat" seats the first and last on the plot's edges
802
+ * (Word's choice for line and area). */
803
+ crossBetween?: "between" | "midCat";
709
804
  }
710
805
  interface ChartData {
711
806
  type: ChartType;
807
+ /** Local name of a plot the renderer does not paint (bar3DChart, radarChart,
808
+ * …). When set, `type` is a placeholder and the renderer draws a labeled box
809
+ * rather than pretending the data is a column chart. */
810
+ unsupported?: string;
712
811
  title?: string;
713
812
  categories: string[];
714
813
  series: ChartSeries[];
814
+ /** c:grouping — how bar/column/area series stack. */
815
+ grouping?: "clustered" | "stacked" | "percentStacked";
816
+ /** Legend edge. Absent when the chart has no c:legend. */
817
+ legend?: "l" | "r" | "t" | "b" | "tr";
818
+ /** c:dLbls showVal on the plot or on every series. */
819
+ dataLabels?: boolean;
820
+ /** c:varyColors — give each point of a single series its own palette slot. */
821
+ varyColors?: boolean;
822
+ categoryAxis?: ChartAxis;
823
+ valueAxis?: ChartAxis;
824
+ /** c:holeSize percent of a doughnut (Word's default is 75). */
825
+ holeSize?: number;
826
+ /** c:gapWidth percent between bar/column categories (Word's default is 150). */
827
+ gapWidth?: number;
828
+ /** c:overlap percent between bars of one category (Word: -27 clustered,
829
+ * 100 stacked). */
830
+ overlap?: number;
831
+ /** c:marker val="1" on a line chart: draw a point marker at each value. */
832
+ markers?: boolean;
833
+ /** Font size in px from c:title//a:defRPr@sz. Word's default title is 14pt. */
834
+ titleSize?: number;
835
+ /** Font size in px from c:txPr//a:defRPr@sz, the chart-wide text size. Word's
836
+ * default for axis labels, legend entries and data labels is 9pt. */
837
+ textSize?: number;
715
838
  }
716
839
  type SmartArtLayout = "process" | "cycle" | "hierarchy" | "list";
717
840
  interface SmartArtData {
@@ -997,7 +1120,10 @@ interface SectionProps {
997
1120
  right?: Border;
998
1121
  offsetFrom: "text" | "page";
999
1122
  };
1000
- /** w:lnNumType: margin line numbering. distance px from the text edge. */
1123
+ /** w:lnNumType: margin line numbering. distance px from the text edge.
1124
+ * start is the raw w:start OFFSET (0 when the attribute is absent, its
1125
+ * literal value otherwise) added to the running per-line count — see
1126
+ * parse/section.ts for why an absent attribute isn't just "start 1". */
1001
1127
  lineNumbering?: {
1002
1128
  countBy: number;
1003
1129
  start: number;
@@ -1009,6 +1135,16 @@ interface SectionProps {
1009
1135
  footnoteNumStart?: number;
1010
1136
  endnoteNumFmt?: string;
1011
1137
  endnoteNumStart?: number;
1138
+ /** w:numRestart: when the mark counter resets. Absent means "continuous"
1139
+ * (the whole document shares one counter — this engine's only honored
1140
+ * value; eachSect/eachPage are round-trip preserved but not laid out). */
1141
+ footnoteNumRestart?: "continuous" | "eachSect" | "eachPage";
1142
+ endnoteNumRestart?: "continuous" | "eachSect" | "eachPage";
1143
+ /** w:pos: where the note text is placed. Round-trip preserved only — the
1144
+ * layout always places footnotes at the page bottom and endnotes at the
1145
+ * document end, regardless of this value. */
1146
+ footnotePos?: "pageBottom" | "beneathText";
1147
+ endnotePos?: "sectEnd" | "docEnd";
1012
1148
  /** w:textDirection tbRl: the whole section flows as East-Asian vertical
1013
1149
  * writing — lines run top-to-bottom, progressing right-to-left. */
1014
1150
  textDirection?: "tbRl";
@@ -1030,6 +1166,10 @@ interface DocComment {
1030
1166
  paraId?: string;
1031
1167
  /** Parent comment id when this comment is a reply (commentsExtended). */
1032
1168
  parentId?: string;
1169
+ /** Thread resolved (w15:commentEx w15:done="1" — the [MS-DOCX] CT_CommentEx
1170
+ * extension; ECMA-376 itself has no resolved state). Meaningful on the
1171
+ * thread parent; Word grays the whole thread from the parent's flag. */
1172
+ resolved?: boolean;
1033
1173
  }
1034
1174
  interface HeaderFooter {
1035
1175
  blocks: Block[];
@@ -1151,10 +1291,10 @@ declare class Package {
1151
1291
  * the table is keyed by element identity and in-place XML mutation preserves
1152
1292
  * identity across `refresh()`.
1153
1293
  */
1154
- type StableId$1 = number;
1294
+ type StableId$2 = number;
1155
1295
  interface EncodedCaret {
1156
- blockId: StableId$1;
1157
- runId: StableId$1;
1296
+ blockId: StableId$2;
1297
+ runId: StableId$2;
1158
1298
  /** Offset in the run's WIRE space: cumulative through the run's inline
1159
1299
  * content in document order, where each w:t contributes its text length
1160
1300
  * and each inline separator (w:tab / w:br / w:cr) contributes ONE unit.
@@ -1198,14 +1338,21 @@ declare class StableIds {
1198
1338
  /** Explicitly assign an id to a newly created node. Local edits allocate
1199
1339
  * (`assign(el)`); applying a replicated edit installs the carried value
1200
1340
  * (`assign(el, carriedId)`). Carried ids must not collide. */
1201
- assign(el: XmlElement, id?: StableId$1): StableId$1;
1341
+ assign(el: XmlElement, id?: StableId$2): StableId$2;
1202
1342
  /** Force `el` to carry `id`, replacing any id it already has (e.g. one
1203
1343
  * auto-assigned by a refresh() before a carried id could be installed).
1204
1344
  * The previous id is retired. Throws if `id` is held by a different element. */
1205
- reassign(el: XmlElement, id: StableId$1): void;
1345
+ reassign(el: XmlElement, id: StableId$2): void;
1346
+ /** Drop an element's mapping entirely; its id retires (never reused —
1347
+ * `next` stays monotonic). Used before carried-id assignment: a refresh
1348
+ * inside a mutation auto-assigns sequential ids to the nodes it created,
1349
+ * and one of those autos can equal a LATER id of the same carried batch,
1350
+ * which would make reassign throw on a perfectly good intent. No-op for an
1351
+ * unmapped element. */
1352
+ unassign(el: XmlElement): void;
1206
1353
  private install;
1207
- idOf(el: XmlElement): StableId$1 | undefined;
1208
- elOf(id: StableId$1): XmlElement | undefined;
1354
+ idOf(el: XmlElement): StableId$2 | undefined;
1355
+ elOf(id: StableId$2): XmlElement | undefined;
1209
1356
  /** Drop mappings for elements no longer reachable from the given roots
1210
1357
  * (deleted content). Keeps the table from growing across long sessions.
1211
1358
  * Ids of dropped elements are retired, never reused. */
@@ -1215,10 +1362,10 @@ declare class StableIds {
1215
1362
  * the tree: `pairs` maps originals→clones (as produced by walking original
1216
1363
  * and cloned roots in step). Used by the reconciliation snapshot (plan
1217
1364
  * doc 03) so a restore re-keys the table to the restored elements. */
1218
- captureForClone(originalToClone: Map<XmlElement, XmlElement>): Map<StableId$1, XmlElement>;
1365
+ captureForClone(originalToClone: Map<XmlElement, XmlElement>): Map<StableId$2, XmlElement>;
1219
1366
  /** Replace the table wholesale from a captured mapping (restore path). */
1220
- restore(fromCapture: Map<StableId$1, XmlElement>, nextId: StableId$1): void;
1221
- nextId(): StableId$1;
1367
+ restore(fromCapture: Map<StableId$2, XmlElement>, nextId: StableId$2): void;
1368
+ nextId(): StableId$2;
1222
1369
  /**
1223
1370
  * Export the table as `(id, path)` pairs, where a path is the structural
1224
1371
  * location of the id'd element within the given roots: `[rootIndex,
@@ -1229,14 +1376,14 @@ declare class StableIds {
1229
1376
  * consistently.
1230
1377
  */
1231
1378
  exportSidecar(roots: XmlElement[]): {
1232
- next: StableId$1;
1233
- entries: [StableId$1, number[]][];
1379
+ next: StableId$2;
1380
+ entries: [StableId$2, number[]][];
1234
1381
  };
1235
1382
  /** Rebuild the table from a sidecar against freshly parsed roots (the
1236
1383
  * snapshot the sidecar was exported from). Replaces any current mappings. */
1237
1384
  importSidecar(roots: XmlElement[], sidecar: {
1238
- next: StableId$1;
1239
- entries: [StableId$1, number[]][];
1385
+ next: StableId$2;
1386
+ entries: [StableId$2, number[]][];
1240
1387
  }): void;
1241
1388
  /** Encode a caret as wire-stable addresses. `t` is the w:t (or other text
1242
1389
  * holder) the caret sits in; the run is its nearest tracked ancestor run,
@@ -1264,6 +1411,8 @@ interface Relationship {
1264
1411
  }
1265
1412
  type Relationships = Map<string, Relationship>;
1266
1413
 
1414
+ /** The two note parts a document can carry — see notePartsHolding. */
1415
+ type NotePart = "footnotes" | "endnotes";
1267
1416
  /**
1268
1417
  * A fully parsed .docx: sections of blocks, styles, numbering, theme, and
1269
1418
  * header/footer parts, with helpers to resolve effective formatting.
@@ -1284,7 +1433,7 @@ declare class DocxDocument {
1284
1433
  /** Header/footer parts keyed by relationship id from document.xml.rels. */
1285
1434
  readonly headers: Map<string, HeaderFooter>;
1286
1435
  readonly footers: Map<string, HeaderFooter>;
1287
- /** Note content by note id (render-only; sources stripped). */
1436
+ /** Note content by note id. */
1288
1437
  readonly footnotes: Map<number, Block[]>;
1289
1438
  readonly endnotes: Map<number, Block[]>;
1290
1439
  /** The separator paragraph controls the gap between its rule and the first
@@ -1297,11 +1446,23 @@ declare class DocxDocument {
1297
1446
  readonly documentRels: Relationships;
1298
1447
  /** settings.xml w:evenAndOddHeaders — enables the "even" header/footer variants. */
1299
1448
  readonly evenAndOddHeaders: boolean;
1449
+ /** settings.xml w:autoHyphenation (§17.15.1.10). This engine's layout does
1450
+ * not hyphenate automatically — the setting is round-trip state that
1451
+ * governs Word's own rendering of the document. */
1452
+ readonly autoHyphenation: boolean;
1453
+ /** settings.xml w:hyphenationZone/@w:val in twips (§17.15.1.53); null when
1454
+ * the document does not declare one (Word defaults to 360 = 0.25"). */
1455
+ readonly hyphenationZoneTwips: number | null;
1456
+ /** settings.xml w:doNotHyphenateCaps (§17.15.1.41). */
1457
+ readonly doNotHyphenateCaps: boolean;
1300
1458
  /** settings.xml w:mirrorMargins — facing-page (book fold) margins: even
1301
1459
  * (verso) pages swap the left/right margins and place the gutter on the
1302
1460
  * inside (right) edge so the binding margin stays on the inner side of
1303
1461
  * each spread. */
1304
1462
  readonly mirrorMargins: boolean;
1463
+ /** settings.xml w:compat w:suppressTopSpacing: the first line of a page
1464
+ * takes its character height, not its authored (exact) line spacing. */
1465
+ readonly suppressTopSpacing: boolean;
1305
1466
  /** settings.xml w:defaultTabStop in px (Word default 0.5"). */
1306
1467
  readonly defaultTabStop: number;
1307
1468
  /** settings.xml w:compat compatibilityMode (12=Word2007, 14=Word2010,
@@ -1310,6 +1471,12 @@ declare class DocxDocument {
1310
1471
  * it (nccih: a Heading1/2 after a page break sits at margin + its before).
1311
1472
  * Absent → treated as current (15). */
1312
1473
  readonly compatibilityMode: number;
1474
+ /** The compatibilityMode settings.xml actually declares, or undefined when
1475
+ * the setting (or settings.xml itself) is missing. `compatibilityMode`
1476
+ * defaults an omitted value to 15, but a table's percentage width needs the
1477
+ * distinction: Word fits the horizontal cell margins inside the table box at
1478
+ * an EXPLICIT 15 and adds them around it when the setting is absent. */
1479
+ readonly declaredCompatibilityMode: number | undefined;
1313
1480
  /** settings.xml m:mathPr/m:defJc — default justification for display
1314
1481
  * equations whose m:oMathParaPr carries no explicit m:jc (Word default:
1315
1482
  * centerGroup — the rows of a broken equation left-align to each other and
@@ -1345,6 +1512,31 @@ declare class DocxDocument {
1345
1512
  private footnotesRoot;
1346
1513
  private footnotesDirty;
1347
1514
  private footnotesRels;
1515
+ /** Retained endnotes.xml tree (endnote insertion + save round-trip). */
1516
+ private endnotesPart;
1517
+ private endnotesRoot;
1518
+ private endnotesDirty;
1519
+ private endnotesRels;
1520
+ /** Retained bibliography sources part (the customXml b:Sources data of
1521
+ * ECMA-376 §22.6), when present. Source-management editing mutates this
1522
+ * tree in place; a document with none gets the part on first create. */
1523
+ private sourcesPart;
1524
+ private sourcesRoot;
1525
+ private sourcesDirty;
1526
+ /** Companion parts written when THIS session created the sources part
1527
+ * (itemProps + its .rels); an arriving part keeps its own companions. */
1528
+ private sourcesAux;
1529
+ /** Retained glossary document part (word/glossary/document.xml, ECMA-376
1530
+ * §17.12: glossaryDocument/docParts/docPart — Word's Quick Parts / Building
1531
+ * Blocks store), when present. Building-block editing mutates this tree in
1532
+ * place; a document with none gets the part on first create. Unlike
1533
+ * headers/footers, a docPart's body is never caret-editable — it is only
1534
+ * ever cloned INTO the main document body (insertBuildingBlock) or captured
1535
+ * OUT of a selection (createBuildingBlock) — so this part carries no
1536
+ * editableRoots()/stable-id integration of its own. */
1537
+ private glossaryPart;
1538
+ private glossaryRoot;
1539
+ private glossaryDirty;
1348
1540
  /** Serialize retained optional parts only once actually mutated, keeping
1349
1541
  * untouched parts byte-identical through save(). */
1350
1542
  private stylesDirty;
@@ -1467,12 +1659,80 @@ declare class DocxDocument {
1467
1659
  */
1468
1660
  numberingTree(create?: boolean): XmlElement | null;
1469
1661
  markNumberingChanged(): void;
1662
+ /** Retained styles.xml tree, or null when the package has no styles part.
1663
+ * Style-definition editing mutates this tree in place. */
1664
+ stylesTree(): XmlElement | null;
1665
+ /**
1666
+ * Re-resolve the style cascade after a definition changed in place.
1667
+ *
1668
+ * A style definition is not addressed by any paragraph's XML, so mutating one
1669
+ * changes how EVERY paragraph resolves without changing a single w:p. Two
1670
+ * things therefore have to be reset by hand: the parsed Styles map every
1671
+ * effective-props call reads, and layoutGlobalSig, which is what makes the
1672
+ * line-break cache treat cached breaks for unchanged paragraph XML as stale.
1673
+ */
1674
+ markStylesChanged(): void;
1675
+ /**
1676
+ * Retained bibliography sources tree (b:Sources), or null when the package
1677
+ * has no sources part. With create=true, a missing part is created and
1678
+ * registered the way Word lays one out (ECMA-376 §22.6 + Part 2 custom XML
1679
+ * data storage): the data itself as customXml/itemN.xml, a datastore-item
1680
+ * properties part (itemPropsN.xml) declaring the Bibliography schema URI as
1681
+ * its schemaRef, a .rels from the item to its properties, a customXml
1682
+ * relationship from the main document part, and the content-type overrides.
1683
+ *
1684
+ * DETERMINISM. Everything written is a pure function of the package —
1685
+ * the item number is the first free one, and the datastore itemID GUID is a
1686
+ * fixed constant rather than Word's random draw — so two replicas creating
1687
+ * the part through the same sequenced operation write identical bytes.
1688
+ */
1689
+ sourcesTree(create?: boolean): XmlElement | null;
1690
+ /**
1691
+ * Invalidate what a sources-part edit changes downstream. Like
1692
+ * markStylesChanged, the part is addressed by no paragraph's XML: a
1693
+ * CITATION field's painted text resolves from the part at layout, so the
1694
+ * layout signature has to drop for unchanged paragraph XML to repaint.
1695
+ */
1696
+ markSourcesChanged(): void;
1697
+ /**
1698
+ * Retained glossary document tree (w:glossaryDocument), or null when the
1699
+ * package has no glossary part. With create=true, a missing part is
1700
+ * created and registered — package part, document relationship,
1701
+ * content-type override — the createNotesPart discipline.
1702
+ *
1703
+ * The glossary part gets none of the sources part's companion machinery
1704
+ * (no datastore item, no random itemID): it is an ordinary WordprocessingML
1705
+ * part named by relationship TYPE, so creation just mints an empty
1706
+ * `<w:glossaryDocument><w:docParts/></w:glossaryDocument>` and wires it up
1707
+ * — closer to createNotesPart than to sourcesTree. A real Word-authored
1708
+ * glossary part additionally carries its own styles.xml / settings.xml /
1709
+ * fontTable.xml; this engine writes none of them, because a docPart's
1710
+ * content is read once — to clone its blocks into the main document, where
1711
+ * they resolve styles against the MAIN document's own styles.xml — and is
1712
+ * never laid out or rendered as its own story the way a header/footer is.
1713
+ *
1714
+ * DETERMINISM: nothing here depends on Word's random draws (no GUID is
1715
+ * written at all — w:docPartPr/w:guid is optional and this engine never
1716
+ * reads it back), so two replicas creating the part through the same
1717
+ * sequenced operation write identical bytes.
1718
+ */
1719
+ glossaryTree(create?: boolean): XmlElement | null;
1720
+ /** Invalidate what a glossary-part edit changes: nothing downstream, since
1721
+ * createBuildingBlock/deleteBuildingBlock touch only the glossary tree, not
1722
+ * any paragraph the layout reads. Exists for the same "explicit intent to
1723
+ * persist" reason markSourcesChanged does. */
1724
+ markGlossaryChanged(): void;
1470
1725
  /**
1471
1726
  * Retained footnotes tree. With create=true, a missing footnotes.xml part
1472
1727
  * is created and registered (with Word's required separator footnotes) so
1473
1728
  * inserted footnotes serialize and round-trip.
1474
1729
  */
1475
1730
  footnotesTree(create?: boolean): XmlElement | null;
1731
+ /** Retained endnotes tree; the endnote mirror of footnotesTree. */
1732
+ endnotesTree(create?: boolean): XmlElement | null;
1733
+ /** Register a new notes part in document.xml.rels and [Content_Types].xml,
1734
+ * and return the part path. The tree itself is the caller's. */
1735
+ private createNotesPart;
1476
1736
  /**
1477
1737
  * Create an empty header/footer part (with a default-type reference in
1478
1738
  * every sectPr) when the document has none - Word does this implicitly the
@@ -1487,7 +1747,29 @@ declare class DocxDocument {
1487
1747
  * whether an ensureHeaderFooter intent has anything to do). */
1488
1748
  hasHfPart(kind: "header" | "footer"): boolean;
1489
1749
  ensureHfPart(kind: "header" | "footer"): XmlElement;
1750
+ /** A w:headerReference / w:footerReference element. */
1751
+ private hfReference;
1752
+ /** Materialize the default body-level sectPr when the document declares no
1753
+ * section properties at all (schema: the body's sectPr is its LAST child). */
1754
+ private ensureBodySectPr;
1755
+ /**
1756
+ * Give every section a header and footer reference of the given variant
1757
+ * type, creating one empty part per band the way Word does the first time
1758
+ * "different first page" (type "first") or "different odd & even pages"
1759
+ * (type "even") is enabled. Sections that already carry a reference of the
1760
+ * type keep it — and its part's content. True when anything was added.
1761
+ */
1762
+ ensureHfVariantParts(type: "first" | "even"): boolean;
1763
+ /** Create and register a new empty header/footer part — package part,
1764
+ * document relationship, content-type override, hfParts entry — with no
1765
+ * section references of its own; the caller decides which sectPrs point at
1766
+ * it and with which w:type. */
1767
+ private createHfPart;
1490
1768
  markFootnotesChanged(): void;
1769
+ markEndnotesChanged(): void;
1770
+ /** Re-derive both id -> blocks maps from the retained trees, so layout sees
1771
+ * an inserted or edited note. */
1772
+ private rederiveNotes;
1491
1773
  /** Called by comment edit commands after mutating the comments tree. */
1492
1774
  markCommentsChanged(): void;
1493
1775
  /**
@@ -1503,23 +1785,78 @@ declare class DocxDocument {
1503
1785
  * nearest preceding w:t.
1504
1786
  */
1505
1787
  commentAnchors(): Map<string, XmlElement[]>;
1506
- /** Flag the footnotes part dirty when `t` lives inside it, so save()
1507
- * re-serializes footnotes.xml. Called by the editor after a text edit; a
1508
- * no-op for body/header/footer targets. */
1788
+ /** Flag a notes part dirty when `t` lives inside it, so save()
1789
+ * re-serializes footnotes.xml / endnotes.xml. Called by the editor after a
1790
+ * text edit; a no-op for body/header/footer targets. */
1509
1791
  markDirtyIfFootnote(t: XmlElement): void;
1792
+ /**
1793
+ * Which note parts hold `el` right now. An operation that DETACHES `el` —
1794
+ * accepting or rejecting a revision, for one — has to ask BEFORE it mutates
1795
+ * and mark the answer afterwards: a detached element belongs to no part, so
1796
+ * a containment test run after the fact reports nothing and save() then
1797
+ * leaves the stale footnotes.xml / endnotes.xml in the package.
1798
+ */
1799
+ notePartsHolding(el: XmlElement): NotePart[];
1800
+ /** Flag the given note parts dirty, so save() re-serializes exactly those. */
1801
+ markNotePartsChanged(parts: readonly NotePart[]): void;
1510
1802
  /** The mutable XML roots (document body, related modeled parts, settings).
1511
1803
  * settingsRoot is always second and always present so its history snapshot
1512
1804
  * index stays stable even when optional related roots are created later. */
1513
1805
  editableRoots(): XmlElement[];
1806
+ /** CT_Settings children that precede w:mirrorMargins in the schema sequence
1807
+ * (§17.15.1.78). Insertions go before the first child that is not a
1808
+ * predecessor, so Word never has to repair settings.xml. */
1809
+ private static readonly SETTINGS_BEFORE_MIRROR;
1810
+ /** The schema predecessors of w:evenAndOddHeaders (§17.10.1): everything up
1811
+ * to mirrorMargins, then the sequence through defaultTableStyle. */
1812
+ private static readonly SETTINGS_BEFORE_EVEN_AND_ODD;
1813
+ /** Set or remove one settings.xml element at its schema position. Null
1814
+ * removes; otherwise the element is (re)inserted before the first child
1815
+ * that is not a schema predecessor. */
1816
+ private setSettingsElement;
1817
+ /** Set or remove one on/off settings.xml toggle at its schema position. */
1818
+ private setSettingsToggle;
1819
+ /** The schema predecessors of w:autoHyphenation: everything through
1820
+ * w:defaultTabStop (§17.15.1.78). Its cluster mates append in order. */
1821
+ private static readonly SETTINGS_BEFORE_AUTO_HYPHENATION;
1822
+ /**
1823
+ * Patch the hyphenation settings (w:autoHyphenation §17.15.1.10,
1824
+ * w:hyphenationZone §17.15.1.53, w:doNotHyphenateCaps §17.15.1.41). Each
1825
+ * present key is written; `zoneTwips: null` removes the zone element. True
1826
+ * when anything changed — the honest no-op a replicated document-scoped
1827
+ * operation needs. This engine's layout does not hyphenate automatically;
1828
+ * the settings govern Word's own rendering of the file.
1829
+ */
1830
+ setHyphenation(patch: {
1831
+ auto?: boolean;
1832
+ zoneTwips?: number | null;
1833
+ noCaps?: boolean;
1834
+ }): boolean;
1514
1835
  /** Toggle the document-global facing-page margin mode in settings.xml. */
1515
1836
  setMirrorMargins(enabled: boolean): void;
1837
+ /** Toggle w:evenAndOddHeaders (§17.10.1) — the document-global switch that
1838
+ * makes even pages use the "even" header/footer variants. */
1839
+ setEvenAndOddHeaders(enabled: boolean): void;
1840
+ /** Register settings.xml in document.xml.rels and [Content_Types].xml when
1841
+ * the package was born without it (a minimal document). */
1842
+ private registerSettingsPart;
1516
1843
  /**
1517
1844
  * Find the parent element of `target` in any modeled XML tree (document
1518
1845
  * body, headers, footers). Linear scan — documents are small and this only
1519
1846
  * runs on structural edits (Enter, paragraph merge).
1520
1847
  */
1521
- /** XML roots that can carry tracked changes: body, headers/footers, footnotes. */
1848
+ /** The header part roots, in package order. A watermark is authored into
1849
+ * every one of them: Word paints it on every page, and a document with a
1850
+ * first-page or even-page header has more than one header part. */
1851
+ headerRoots(): XmlElement[];
1852
+ /** The footer part roots, in package order — headerRoots' counterpart, for
1853
+ * operations that walk both bands (the page-number gallery's removal
1854
+ * sweep). */
1855
+ footerRoots(): XmlElement[];
1856
+ /** XML roots that can carry tracked changes: body, headers/footers, notes. */
1522
1857
  revisionRoots(): XmlElement[];
1858
+ /** Body, header/footer and note roots — every tree the caret can reach. */
1859
+ private contentRoots;
1523
1860
  /**
1524
1861
  * Memoized child→parent links. Nothing invalidates this map — the tree is
1525
1862
  * spliced constantly — so every answer is RE-DERIVED before it is returned:
@@ -1566,6 +1903,27 @@ declare class DocxDocument {
1566
1903
  saveAsync(): Promise<Uint8Array>;
1567
1904
  private buildPackage;
1568
1905
  private buildPackageFiles;
1906
+ /**
1907
+ * Leave out the chart parts the document no longer references.
1908
+ *
1909
+ * Deleting a chart splices its w:drawing out of the story, but the chart
1910
+ * part, its rels part, its embedded workbook, the document relationship, and
1911
+ * the two [Content_Types].xml overrides all stay. An agent that inserts a
1912
+ * chart, deletes it, and inserts a replacement therefore saves TWO chart
1913
+ * parts for the one chart the document shows.
1914
+ *
1915
+ * The release happens here, at save time, rather than when the drawing goes,
1916
+ * because undo restores the drawing XML — r:id and all — from a snapshot
1917
+ * that models package parts but no relationship state. Dropping the
1918
+ * relationship early would make undo produce a chart pointing at nothing.
1919
+ * The live tree keeps everything; only the written bytes lose the orphans,
1920
+ * and the saveJournal puts back the two trees this touches.
1921
+ *
1922
+ * Relationship ids are scoped to the part that owns the rels file, so the
1923
+ * document body is the only place that can reference these ids, and reading
1924
+ * it is a complete check. Headers, footers, and notes carry their own rels.
1925
+ */
1926
+ private dropOrphanChartParts;
1569
1927
  /** Fresh unique docPr id for inserted drawings. Seeded once past the
1570
1928
  * highest id already present in any editable root (floor 1000, matching
1571
1929
  * the historical seed for documents with no drawings) so a document that
@@ -1585,6 +1943,22 @@ declare class DocxDocument {
1585
1943
  addHyperlinkRel(url: string): string;
1586
1944
  /** Retarget an existing external relationship (hyperlink href edit). */
1587
1945
  setRelTarget(relId: string, url: string): boolean;
1946
+ /** The relationships of the part that holds `source`: a header or footer
1947
+ * part when the element is inside one, else the document part. */
1948
+ private imageRelsOwner;
1949
+ /** Add an image relationship pointing at `part`, in the relationships of
1950
+ * whichever part holds `source`. */
1951
+ private addImageRel;
1952
+ /**
1953
+ * Point a SECOND part at an image part this document already has.
1954
+ *
1955
+ * Word's picture watermark is ONE media part that every header part
1956
+ * references. Registering the image again per header would put a full copy
1957
+ * of the bytes in the package for each one — three headers, three copies of
1958
+ * the same logo — and give the media-install path three pending parts to
1959
+ * fill from one upload.
1960
+ */
1961
+ linkImageResource(part: string, source: XmlElement): string;
1588
1962
  private addImageResourceAt;
1589
1963
  addImageResource(bytes: Uint8Array, ext: string): string;
1590
1964
  /** Add a GLB model part and its Office 2019 model3d relationship. */
@@ -1659,6 +2033,15 @@ declare class DocxDocument {
1659
2033
  iv?: string;
1660
2034
  genesisId?: string;
1661
2035
  }, source?: XmlElement): string;
2036
+ /** As registerPendingImage, and also names the part it made — what a second
2037
+ * part needs to reach the same image through linkImageResource. */
2038
+ registerPendingImagePart(sha: string, ext: string, meta?: {
2039
+ iv?: string;
2040
+ genesisId?: string;
2041
+ }, source?: XmlElement): {
2042
+ relId: string;
2043
+ part: string;
2044
+ };
1662
2045
  /** Install fetched bytes into a pending part (doc 05). The caller has
1663
2046
  * ALREADY verified the sha against the intent's declaration (the
1664
2047
  * reservation is the hash commitment — doc 16 §1.1); this installs and
@@ -1680,6 +2063,776 @@ declare class DocxDocument {
1680
2063
  private readXmlOptional;
1681
2064
  }
1682
2065
 
2066
+ /** Outline/shadow for an ordinary run — Word's Home-tab "Text Effects and
2067
+ * Typography" gallery, distinct from inserting a WordArt object. */
2068
+ interface RunTextEffectPatch {
2069
+ outline?: {
2070
+ color: string;
2071
+ widthPt: number;
2072
+ } | null;
2073
+ shadow?: boolean;
2074
+ }
2075
+ /** bodyPr's autofit choice: grow the shape, shrink the text, or neither. */
2076
+ type DrawingTextFitMode = "none" | "resizeShape" | "shrinkText";
2077
+
2078
+ interface RunFormatPatch {
2079
+ bold?: boolean;
2080
+ italic?: boolean;
2081
+ underline?: boolean;
2082
+ strike?: boolean;
2083
+ /** "#RRGGBB"; null removes the direct color. */
2084
+ color?: string | null;
2085
+ /** Word highlight name ("yellow", "cyan", …); null removes. */
2086
+ highlight?: string | null;
2087
+ /** Font size in points. */
2088
+ fontSizePt?: number;
2089
+ fontFamily?: string;
2090
+ /** Superscript/subscript; null returns the run to the baseline. */
2091
+ verticalAlign?: "superscript" | "subscript" | null;
2092
+ /**
2093
+ * Character style (w:rStyle); null removes the reference.
2094
+ *
2095
+ * This rides the run patch rather than taking an operation of its own
2096
+ * because applying a character style to PART of a run splits the run — which
2097
+ * breaks the registry's position-stable precondition, and which formatRange
2098
+ * already handles with its carried before/middle/after piece ids.
2099
+ */
2100
+ characterStyleId?: string | null;
2101
+ /**
2102
+ * w14 outline/shadow run effects (Word's Home-tab "Text Effects and
2103
+ * Typography" gallery) — the same vocabulary a WordArt object's text
2104
+ * carries, applied directly to ordinary runs. null removes every w14
2105
+ * effect, reverting to plain text. Rides the run patch rather than an
2106
+ * operation of its own for the same reason characterStyleId does: applying
2107
+ * it to PART of a run splits the run, which formatRange already handles.
2108
+ */
2109
+ textEffect?: RunTextEffectPatch | null;
2110
+ /** Remove all direct character formatting (and character style). */
2111
+ clear?: boolean;
2112
+ }
2113
+
2114
+ /**
2115
+ * CITATION resolution: the document's bibliography sources and the simple
2116
+ * parenthetical and bibliography-entry formats Word paints for the built-in
2117
+ * styles.
2118
+ *
2119
+ * WHERE THE SOURCES LIVE. Word stores the bibliography source list as a
2120
+ * Custom XML Data part (customXml/item1.xml in Word's own files), targeted
2121
+ * from the main document part by a customXml relationship. The markup is the
2122
+ * Bibliography namespace of ECMA-376 §22.6: a b:Sources root whose
2123
+ * StyleName attribute names the selected citation style ("APA", "MLA", …)
2124
+ * and whose b:Source children each carry a b:Tag the CITATION instruction
2125
+ * references. The part is retained by DocxDocument (sourcesTree) so the
2126
+ * source-management operations in edit/sources.ts can mutate it; a part
2127
+ * those operations never touch keeps its original bytes through save().
2128
+ *
2129
+ * WHAT IS FORMATTED. The author-date parenthetical of the simple built-in
2130
+ * styles: "(Author, Year)" for the APA-shaped family and "(Author)" /
2131
+ * "(Author page)" for MLA — plus the matching bibliography ENTRY per source
2132
+ * (bibliographyEntryText below). Full style-sheet fidelity (Word ships an
2133
+ * XSL per style) is out of scope; a CITATION whose display this module
2134
+ * cannot build keeps its cached result, which is Word's own rendering.
2135
+ *
2136
+ * It lives here, above both consumers, for the style-ref.ts reason: layout
2137
+ * paints what the reader sees and the update pass writes what the saved file
2138
+ * carries, and the two must not disagree about the same field.
2139
+ */
2140
+ /** A person author, in b:NameList order. */
2141
+ interface BibliographyPerson {
2142
+ last: string;
2143
+ first?: string;
2144
+ }
2145
+ /** The citation styles the style selector offers: the two whose parenthetical
2146
+ * and bibliography-entry rules this module models. One list, so the operation
2147
+ * validator, the agent schema, and the toolbar cannot disagree. */
2148
+ declare const CITATION_STYLES: readonly ["APA", "MLA"];
2149
+ type CitationStyle = (typeof CITATION_STYLES)[number];
2150
+
2151
+ /** An a:srcRect crop as fractions of the source bitmap trimmed off each edge.
2152
+ * The four together must leave a visible strip on both axes. */
2153
+ interface ImageCrop {
2154
+ l: number;
2155
+ t: number;
2156
+ r: number;
2157
+ b: number;
2158
+ }
2159
+
2160
+ /**
2161
+ * Numbering DEFINITION editing: the levels of an abstract numbering
2162
+ * definition, and the per-instance overrides that restart or continue a
2163
+ * sequence. Applying numbering to a paragraph lives in lists.ts.
2164
+ *
2165
+ * Two things are edited here, and the difference matters:
2166
+ *
2167
+ * - A LEVEL of an abstract definition (w:abstractNum/w:lvl). Every list
2168
+ * instance sharing that abstract definition changes with it.
2169
+ * - An OVERRIDE on one instance (w:num/w:lvlOverride). Only the paragraphs
2170
+ * carrying that numId change, which is how one list restarts at 1 while
2171
+ * another sharing the same look keeps counting.
2172
+ */
2173
+ /** The numbering formats Word offers for a level. */
2174
+ declare const NUMBER_FORMATS: readonly ["decimal", "decimalZero", "upperRoman", "lowerRoman", "upperLetter", "lowerLetter", "ordinal", "bullet", "none"];
2175
+ type NumberFormat = (typeof NUMBER_FORMATS)[number];
2176
+ /** What one level of a multilevel definition can be changed to. Undefined
2177
+ * leaves a property alone. */
2178
+ interface LevelPatch {
2179
+ format?: NumberFormat;
2180
+ /** The label template: "%1." or "%1.%2." for a multilevel definition, or the
2181
+ * bullet glyph when format is "bullet". */
2182
+ text?: string;
2183
+ /** The counter this level starts at. */
2184
+ start?: number;
2185
+ alignment?: "left" | "center" | "right";
2186
+ /** Text indent, in points. */
2187
+ indentLeftPt?: number;
2188
+ /** Hanging indent of the label, in points. */
2189
+ hangingPt?: number;
2190
+ }
2191
+
2192
+ /** The w:val values w:tblBorders / w:tcBorders edges accept. "none" writes
2193
+ * w:val="nil", Word's spelling for an explicitly suppressed rule. */
2194
+ type TableBorderStyle = "single" | "thick" | "double" | "dotted" | "dashed" | "dotDash" | "dotDotDash" | "thinThickSmallGap" | "triple" | "wave" | "none";
2195
+ /** One border edge. Table scope carries the four sides plus the two inside
2196
+ * rules; cell scope carries the four sides plus the two diagonals. Neither
2197
+ * carries the other's — the parser reads only these, so writing the rest
2198
+ * would emit XML that renders nothing. */
2199
+ type TableBorderEdge = "top" | "bottom" | "left" | "right" | "insideH" | "insideV" | "tl2br" | "tr2bl";
2200
+ interface TableBorderSpec {
2201
+ style: TableBorderStyle;
2202
+ /** Stroke width in eighths of a point (w:sz). Word's UI offers 2..48. */
2203
+ sz?: number;
2204
+ /** "#RRGGBB", "RRGGBB", or "auto". */
2205
+ color?: string;
2206
+ /** Gap between rule and content, in points (w:space). */
2207
+ space?: number;
2208
+ }
2209
+ /** Word's six "Table Style Options" checkboxes. Banding is expressed
2210
+ * positively here and inverted into w:noHBand / w:noVBand on write — the
2211
+ * negative spelling is a wire detail, and every caller that had to remember
2212
+ * the inversion got it wrong at least once. */
2213
+ interface TableLookToggles {
2214
+ firstRow: boolean;
2215
+ lastRow: boolean;
2216
+ firstColumn: boolean;
2217
+ lastColumn: boolean;
2218
+ bandedRows: boolean;
2219
+ bandedCols: boolean;
2220
+ }
2221
+ /** Cell padding in points. An omitted side is left as it was; pass null to
2222
+ * setTableCellMargins to drop the whole override. */
2223
+ interface CellMarginsPt {
2224
+ top?: number;
2225
+ left?: number;
2226
+ bottom?: number;
2227
+ right?: number;
2228
+ }
2229
+
2230
+ /**
2231
+ * Style DEFINITION editing: the entries in styles.xml, as opposed to applying
2232
+ * an existing style to content (setParagraphStyle in blocks.ts, w:rStyle via
2233
+ * the run format patch).
2234
+ *
2235
+ * Everything here mutates the retained styles.xml tree and then calls
2236
+ * doc.markStylesChanged(), which re-parses the tree and drops the layout
2237
+ * signature. That is the whole of the cascade re-resolution: a definition is
2238
+ * not addressed by any paragraph's XML, so no w:p changes and the model
2239
+ * re-derives effective props from the new Styles map on the next layout.
2240
+ */
2241
+ /** The paragraph properties a style definition can carry, in points.
2242
+ * Null clears the property; undefined leaves it alone. */
2243
+ interface StyleParaPatch {
2244
+ alignment?: "left" | "center" | "right" | "both" | null;
2245
+ spacingBeforePt?: number | null;
2246
+ spacingAfterPt?: number | null;
2247
+ /** Line spacing as a multiple of single (1.5 → w:line="360" auto). */
2248
+ lineMultiple?: number | null;
2249
+ indentLeftPt?: number | null;
2250
+ indentFirstLinePt?: number | null;
2251
+ keepNext?: boolean | null;
2252
+ /** w:outlineLvl 0-8 — what makes a paragraph style a TOC heading level. */
2253
+ outlineLevel?: number | null;
2254
+ }
2255
+ /** The run properties a style definition can carry. Same names as direct
2256
+ * character formatting; `clear` has no meaning for a definition. */
2257
+ type StyleRunPatch = Omit<RunFormatPatch, "clear">;
2258
+ /** The four style kinds a w:style can declare. One list, so a validator and
2259
+ * a schema cannot disagree about which types exist. */
2260
+ declare const STYLE_TYPES: readonly ["paragraph", "character", "table", "numbering"];
2261
+ type StyleType = (typeof STYLE_TYPES)[number];
2262
+ interface StyleSpec {
2263
+ styleId: string;
2264
+ type: StyleType;
2265
+ /** The display name (w:name) — what a gallery shows. */
2266
+ name: string;
2267
+ /** Parent in the cascade. Defaults per type to what Word writes: Normal for
2268
+ * a paragraph style, DefaultParagraphFont for a character style,
2269
+ * TableNormal for a table style, and nothing for a numbering style. */
2270
+ basedOn?: string | null;
2271
+ /** Style applied to the NEXT paragraph after this one (paragraph only). */
2272
+ next?: string | null;
2273
+ /** w:qFormat — show the style in the quick-style gallery. */
2274
+ quickStyle?: boolean;
2275
+ /** w:uiPriority — gallery sort order. */
2276
+ uiPriority?: number;
2277
+ paragraph?: StyleParaPatch;
2278
+ run?: StyleRunPatch;
2279
+ /**
2280
+ * PARAGRAPH styles only: also write the linked character companion Word
2281
+ * pairs with one, so the same look can be applied to a span of text as well
2282
+ * as to a whole paragraph. The companion takes the id `<styleId>Char` and
2283
+ * the name `<name> Char`, copies the paragraph style's run properties, and
2284
+ * the two point at each other through w:link.
2285
+ *
2286
+ * Refused when `<styleId>Char` is already taken, rather than picking
2287
+ * another id: the companion's id has to be derivable from the paragraph
2288
+ * style's, or two replicas applying the same operation would disagree
2289
+ * about what to call it.
2290
+ */
2291
+ linked?: boolean;
2292
+ /** TABLE styles only: the grid the style draws. Conditional formats
2293
+ * (w:tblStylePr — banded rows, header row) are not expressible yet. */
2294
+ table?: {
2295
+ borders?: Partial<Record<TableBorderEdge, TableBorderSpec>>;
2296
+ };
2297
+ /** NUMBERING styles only, and required for them: the w:numId of the
2298
+ * numbering definition the style names. A numbering style is a NAME for a
2299
+ * list definition, so it carries nothing else of its own. */
2300
+ numbering?: {
2301
+ numId: number;
2302
+ };
2303
+ }
2304
+ interface StylePatch {
2305
+ name?: string;
2306
+ basedOn?: string | null;
2307
+ next?: string | null;
2308
+ quickStyle?: boolean;
2309
+ uiPriority?: number;
2310
+ paragraph?: StyleParaPatch;
2311
+ run?: StyleRunPatch;
2312
+ }
2313
+
2314
+ interface Model3DRotation {
2315
+ x: number;
2316
+ y: number;
2317
+ z: number;
2318
+ }
2319
+
2320
+ /**
2321
+ * Bibliography SOURCE editing: the b:Source entries of the customXml sources
2322
+ * part (ECMA-376 §22.6), as opposed to citing one (insertCitationField in
2323
+ * fields.ts) or rendering one (src/citations.ts).
2324
+ *
2325
+ * Everything here mutates the retained sources tree and then calls
2326
+ * doc.markSourcesChanged() — the styles.ts discipline. The part is created on
2327
+ * the first source (doc.sourcesTree(true)); only the sources part is written,
2328
+ * so a package whose sources this engine never touches keeps its original
2329
+ * bytes through save().
2330
+ */
2331
+ /** The source kinds the manager offers, mapped to the b:SourceType values
2332
+ * Word's own Source Manager writes. The four cover the common cases; an
2333
+ * arriving source of any other type still renders and can be cited. */
2334
+ declare const CITATION_SOURCE_TYPES: readonly ["book", "article", "website", "report"];
2335
+ type CitationSourceType = (typeof CITATION_SOURCE_TYPES)[number];
2336
+ interface CitationSourceSpec {
2337
+ /** Word's Source-Manager tag shape (isValidCitationTag): what a CITATION
2338
+ * instruction references. */
2339
+ tag: string;
2340
+ type: CitationSourceType;
2341
+ /** Person authors. Mutually exclusive with `corporate`. */
2342
+ authors?: BibliographyPerson[];
2343
+ /** Corporate author (b:Corporate). */
2344
+ corporate?: string;
2345
+ title?: string;
2346
+ year?: string;
2347
+ /** Books and reports. */
2348
+ publisher?: string;
2349
+ /** Journal articles (b:JournalName). */
2350
+ journal?: string;
2351
+ /** Internet sites. */
2352
+ url?: string;
2353
+ }
2354
+ /** Everything but the tag, each field optional; an empty string clears the
2355
+ * field. `authors`/`corporate` replace the whole author element. */
2356
+ type CitationSourcePatch = Partial<Omit<CitationSourceSpec, "tag">>;
2357
+
2358
+ declare const PARAGRAPH_BORDER_EDGES: readonly ["top", "left", "bottom", "right", "between", "bar"];
2359
+ type ParagraphBorderEdge = (typeof PARAGRAPH_BORDER_EDGES)[number];
2360
+ interface ParagraphBordersPatch {
2361
+ /** Edges to change: a spec writes the rule, null removes the direct edge.
2362
+ * Absent edges are left alone. The spec vocabulary is the table border
2363
+ * picker's (style / sz in eighths / color / space in points). */
2364
+ borders?: Partial<Record<ParagraphBorderEdge, TableBorderSpec | null>>;
2365
+ /** Paragraph shading fill "RRGGBB"; null removes the direct w:shd.
2366
+ * Undefined leaves shading alone. */
2367
+ shading?: string | null;
2368
+ }
2369
+ declare const TAB_STOP_ALIGNMENTS: readonly ["left", "center", "right", "decimal", "bar"];
2370
+ declare const TAB_STOP_LEADERS: readonly ["none", "dot", "hyphen", "underscore", "middleDot"];
2371
+ interface TabStopSpec {
2372
+ /** Position in points from the left text edge. */
2373
+ posPt: number;
2374
+ align: (typeof TAB_STOP_ALIGNMENTS)[number];
2375
+ leader: (typeof TAB_STOP_LEADERS)[number];
2376
+ }
2377
+
2378
+ /** The w:pgNumType number formats the layout engine paints (its PAGE_FMT
2379
+ * table); the editable subset of ST_NumberFormat (ECMA-376 §17.18.59). */
2380
+ declare const PAGE_NUMBER_FORMATS: readonly ["decimal", "lowerRoman", "upperRoman", "lowerLetter", "upperLetter"];
2381
+ type PageNumberFormat = (typeof PAGE_NUMBER_FORMATS)[number];
2382
+ /** Note-mark numbering formats the layout engine paints (formatNoteMark's
2383
+ * table): the page-number format subset plus "chicago", Word's symbol style
2384
+ * (*, †, ‡, §) — footnotes' traditional default in some templates. */
2385
+ declare const NOTE_NUMBER_FORMATS: readonly ["decimal", "lowerRoman", "upperRoman", "lowerLetter", "upperLetter", "chicago"];
2386
+ type NoteNumberFormat = (typeof NOTE_NUMBER_FORMATS)[number];
2387
+ /** ST_RestartNumber (ECMA-376 §17.18.81): when the mark counter resets.
2388
+ * Only "eachSect" is honored by layout (assignNoteNumbers); "continuous" is
2389
+ * the OOXML default; "eachPage" round-trips but is not laid out — see
2390
+ * assignNoteNumbers' comment for why. */
2391
+ declare const NOTE_RESTART_VALUES: readonly ["continuous", "eachSect", "eachPage"];
2392
+ type NoteRestart = (typeof NOTE_RESTART_VALUES)[number];
2393
+
2394
+ declare const PAGE_NUMBER_POSITIONS: readonly ["top", "bottom"];
2395
+ type PageNumberGalleryPosition = (typeof PAGE_NUMBER_POSITIONS)[number];
2396
+ declare const PAGE_NUMBER_ALIGNMENTS: readonly ["left", "center", "right"];
2397
+ type PageNumberGalleryAlign = (typeof PAGE_NUMBER_ALIGNMENTS)[number];
2398
+ declare const HEADER_FOOTER_PRESETS: readonly ["blank", "centeredTitle", "titleAndDate", "threeColumn"];
2399
+ type HeaderFooterPreset = (typeof HEADER_FOOTER_PRESETS)[number];
2400
+
2401
+ /**
2402
+ * A native Word table of contents: a TOC field whose cached result is the
2403
+ * entry list.
2404
+ *
2405
+ * WHY A FIELD AND NOT PLAIN PARAGRAPHS. Word recognises a TOC only by its
2406
+ * field structure, and everything a user expects from one — "Update Table",
2407
+ * the grey field shading, Ctrl-click navigation — follows from it. A pile of
2408
+ * paragraphs that merely looks like a TOC is a document Word cannot maintain.
2409
+ *
2410
+ * THE STRUCTURE, as Word writes it (verified against the parity corpus's
2411
+ * Word-authored TOCs, e.g. wild2-med-nccih-protocol.docx):
2412
+ *
2413
+ * <w:p> first entry paragraph, pStyle TOC1
2414
+ * fldChar begin
2415
+ * instrText ` TOC \o "1-3" \h \z \u `
2416
+ * fldChar separate
2417
+ * <w:hyperlink w:anchor="_Toc…" w:history="1"> … </w:hyperlink>
2418
+ * </w:p>
2419
+ * <w:p> … </w:p> one paragraph per further entry
2420
+ * <w:p> fldChar end </w:p> closes the field
2421
+ *
2422
+ * The field's begin/separate live in the FIRST entry paragraph rather than in
2423
+ * a paragraph of their own, and everything between separate and end is the
2424
+ * cached result. Each entry is a hyperlink to the heading's `_Toc` bookmark,
2425
+ * holding the title, a tab to a right-aligned dot-leader stop, and a PAGEREF
2426
+ * field for the page number.
2427
+ *
2428
+ * HOW IT STAYS CURRENT. The entries' PAGEREF fields are ordinary complex
2429
+ * fields, so the update pass (edit/update-fields.ts) repages the whole table
2430
+ * with no TOC-specific code: it harvests each PAGEREF's page from a layout
2431
+ * like any other. Only a change to the HEADING SET needs rebuildToc, which
2432
+ * replaces the entry paragraphs outright.
2433
+ */
2434
+ /** Levels a `\o` switch includes, e.g. [1, 3] for `\o "1-3"`. */
2435
+ type TocLevels = [number, number];
2436
+ /** The tab leaders a TOC entry can draw. One list, so a validator and a
2437
+ * schema cannot disagree about which exist. */
2438
+ declare const TOC_LEADERS: readonly ["dot", "hyphen", "underscore", "none"];
2439
+ type TocLeader = (typeof TOC_LEADERS)[number];
2440
+
2441
+ /**
2442
+ * The operation registry: ONE declaration per edit operation, read by every
2443
+ * surface that used to carry its own hand-written copy.
2444
+ *
2445
+ * Adding an operation used to cost four to six coordinated edits — a core
2446
+ * mutation, an editor dispatch, a wire intent variant in TWO packages, a
2447
+ * transform/validate case, an agent capability row, an agent id-budget case.
2448
+ * Each of those is guarded by a compile-time exhaustiveness gate, so nothing
2449
+ * could silently go missing; the cost was the coordination, not the risk. A
2450
+ * registered operation is declared once here, and the gates then consume the
2451
+ * registry instead of a second hand-maintained list. The gates are NOT
2452
+ * relaxed: an operation that is not registered still has to satisfy every one
2453
+ * of them by hand.
2454
+ *
2455
+ * WHAT MAY BE REGISTERED. The declaration shape below is deliberately narrow.
2456
+ * A registered operation must be:
2457
+ *
2458
+ * 1. ADDRESSED BY STABLE ID — a run, a paragraph, or a table cell paragraph.
2459
+ * The address is the whole of its collaborative "honest no-op" predicate:
2460
+ * when the id does not resolve in the room, the operation applies as a
2461
+ * clean rejection everywhere rather than mutating anything locally.
2462
+ * 2. POSITION-STABLE — it moves no run's text, so a concurrent intent's
2463
+ * offsets need no remapping and its transform is identity. The
2464
+ * text-shaped intents (insertText, deleteText, splitParagraph,
2465
+ * formatRange) each carry bespoke transform logic and stay hand-written.
2466
+ * 3. WITHOUT A WIRE INVERSE — collaborative undo skips it, which is the
2467
+ * status quo for every intent except the four in @wordinweb/collab's
2468
+ * invert.ts. The local path still takes a history checkpoint.
2469
+ *
2470
+ * Those three preconditions ARE the operation's undo and transform
2471
+ * classification. They are stated once, here, instead of repeated per
2472
+ * operation, because every operation the registry admits shares them; an
2473
+ * operation that breaks one of them does not belong in the registry yet.
2474
+ */
2475
+ /** A stable id from the core side table (the wire's addressing unit). */
2476
+ type StableId$1 = number;
2477
+ /**
2478
+ * How a registered operation names its target on the wire.
2479
+ *
2480
+ * "document" scopes an operation to the whole document, which means it has no
2481
+ * stable id and therefore none of the honest-no-op protection an id gives: a
2482
+ * document address ALWAYS resolves. Such an operation has to supply its own
2483
+ * rejection predicate from the payload — see updateFields below, whose result
2484
+ * count must match the document's field count — and it must carry every value
2485
+ * a replica cannot re-derive identically.
2486
+ *
2487
+ * "object" names a DRAWING: the stable id of the run that CARRIES it, plus an
2488
+ * `objectIndex` into that run's content picking out which drawing it is (a run
2489
+ * can hold several). This is the addressing every hand-written drawing intent
2490
+ * already uses — setImageWrap, resizeDrawing — so a migrated one keeps its
2491
+ * wire shape. The index is NOT in the table below: it is a position inside the
2492
+ * run rather than an id of its own, which is also why it stays out of the
2493
+ * agent-facing field list, where a raw index is forbidden. BOTH halves reject:
2494
+ * an id nobody has and an index that no longer names a drawing are each the
2495
+ * same clean no-op, so the honest-no-op predicate is exactly the one every
2496
+ * addressed operation has. The index's WELL-FORMEDNESS is checked centrally
2497
+ * (see validateRegisteredOperation) rather than by each operation, for the
2498
+ * same reason the three preconditions above are stated once.
2499
+ */
2500
+ type OperationAddress = "run" | "block" | "cell" | "object" | "document";
2501
+ /**
2502
+ * Agent capability category. Mirrors @wordinweb/agent's
2503
+ * AgentEditCapability["category"]; the agent's typed capability map is what
2504
+ * checks the two stay equal.
2505
+ */
2506
+ type OperationCategory = "text" | "paragraph" | "review" | "table" | "insert" | "drawing" | "math" | "document";
2507
+ /** An agent-facing payload field beyond the address reference. Order is the
2508
+ * order the agent's JSON schema lists them in. */
2509
+ interface OperationField {
2510
+ name: string;
2511
+ /** Absent means required. */
2512
+ optional?: true;
2513
+ }
2514
+ /** What an address resolved to in the document. */
2515
+ interface OperationTarget {
2516
+ /** The addressed element: the w:r, the w:p, or the w:tbl owning the cell. */
2517
+ el: XmlElement;
2518
+ /** The first w:t under a run, or the first text descendant of a paragraph.
2519
+ * Null when the target carries no text (and for cell addressing). */
2520
+ t: XmlElement | null;
2521
+ /** The parsed run for a run address, null for the other two. Needed by
2522
+ * operations whose state is reachable only through the model — the checkbox
2523
+ * marker parsing hangs on a run's content — rather than from the XML. */
2524
+ run: Run | null;
2525
+ /**
2526
+ * For cell addressing: the addressed w:p itself. `el` deliberately widens a
2527
+ * cell address to the owning w:tbl, which is what a table-scoped operation
2528
+ * wants; a CELL-scoped one (per-edge borders, a margin override) needs the
2529
+ * one cell the caret is in, and the paragraph is how it gets there. Null
2530
+ * for run and block addressing, whose addressed element IS `el`.
2531
+ */
2532
+ cellParagraph: XmlElement | null;
2533
+ /** For object addressing: the w:drawing (or VML shape) the address named.
2534
+ * Null for every other address. */
2535
+ drawing: XmlElement | null;
2536
+ }
2537
+ interface OperationContext<Payload> {
2538
+ doc: DocxDocument;
2539
+ target: OperationTarget;
2540
+ payload: Payload;
2541
+ }
2542
+ /**
2543
+ * The caller-supplied part of a wire payload: everything except the address
2544
+ * field the dispatcher fills in and the carried ids it allocates.
2545
+ */
2546
+ type OperationArgs<Payload> = Omit<Payload, "runId" | "blockId" | "cellParagraphId" | "nodeIds">;
2547
+ interface OperationDefinition<Kind extends string, Payload> {
2548
+ kind: Kind;
2549
+ address: OperationAddress;
2550
+ /** Agent capability row: how the operation is grouped and described. */
2551
+ category: OperationCategory;
2552
+ description: string;
2553
+ /** Agent-facing fields beyond the address reference, in schema order. */
2554
+ fields: readonly OperationField[];
2555
+ /**
2556
+ * How many fresh stable ids the mutation needs for the id-tracked nodes it
2557
+ * creates. Omit when it creates none. Every producer (the editor, the React
2558
+ * host, the agent compiler) reads this instead of repeating the arithmetic.
2559
+ */
2560
+ nodeIds?: (args: OperationArgs<Payload>) => number;
2561
+ /** The mutation removes id-tracked nodes, so the caller must retire their
2562
+ * stable ids afterwards. Deletion and pruning are paired everywhere else in
2563
+ * the apply path (mergeParagraph, removeDrawing); declaring it here keeps
2564
+ * the pairing in the operation's single declaration. */
2565
+ prunesIds?: true;
2566
+ /**
2567
+ * Reject a malformed payload before it is sequenced. Runs on both sides of
2568
+ * the wire, so it must be a pure function of the payload.
2569
+ */
2570
+ validate?: (payload: Payload) => string | null;
2571
+ /**
2572
+ * The XML mutation, headless and from a resolved target. False means a
2573
+ * clean no-op: the operation applied nothing and every replica agrees.
2574
+ */
2575
+ apply: (ctx: OperationContext<Payload>) => boolean;
2576
+ }
2577
+ /**
2578
+ * The optional suggest payload a TRACKABLE operation carries, and the
2579
+ * validation they share.
2580
+ *
2581
+ * With it the operation records what it replaced — w:pPrChange for a list
2582
+ * marker, w:tblPrChange / w:trPrChange / w:tcPrChange for table formatting —
2583
+ * instead of mutating outright, so a reviewer can accept or reject it. The
2584
+ * author and date travel in the payload so every replica writes byte-identical
2585
+ * XML; the w:id is scan-derived from identical tree state and needs no
2586
+ * carrying. Omitting it is a direct, untracked edit.
2587
+ */
2588
+ interface SuggestablePayload {
2589
+ suggest?: {
2590
+ author: string;
2591
+ date: string;
2592
+ };
2593
+ }
2594
+ /** A payload with no fields of its own. Not `Record<string, never>`: that
2595
+ * carries an index signature, which would forbid the clientId/clientSeq/base
2596
+ * bookkeeping @wordinweb/collab intersects onto every wire body. */
2597
+ type NoPayload = Record<never, never>;
2598
+ declare const OPERATIONS: readonly [OperationDefinition<"setListType", {
2599
+ blockId: StableId$1;
2600
+ listKind: "bullet" | "number" | null;
2601
+ /** Additional target paragraphs beyond the addressed one, sharing its
2602
+ * minted numbering definition. Absent = the old single-paragraph form. */
2603
+ moreBlockIds?: StableId$1[];
2604
+ } & SuggestablePayload>, OperationDefinition<"insertTable", {
2605
+ runId: StableId$1;
2606
+ rows: number;
2607
+ cols: number;
2608
+ cells?: string[][];
2609
+ headerRow?: boolean;
2610
+ nodeIds: StableId$1[];
2611
+ }>, OperationDefinition<"resizeTableRow", {
2612
+ cellParagraphId: StableId$1;
2613
+ rowIdx: number;
2614
+ heightPx: number;
2615
+ }>, OperationDefinition<"toggleCheckbox", {
2616
+ runId: StableId$1;
2617
+ }>, OperationDefinition<"updateFields", {
2618
+ results: string[];
2619
+ }>, OperationDefinition<"insertToc", {
2620
+ runId: StableId$1;
2621
+ levels?: TocLevels;
2622
+ leader?: TocLeader;
2623
+ /** With a label the field is a TABLE OF FIGURES (`TOC \c "Label"`): the
2624
+ * entries come from the label's caption paragraphs instead of headings. */
2625
+ captionLabel?: string;
2626
+ entryCount: number;
2627
+ nodeIds: StableId$1[];
2628
+ }>, OperationDefinition<"insertCaption", {
2629
+ blockId: StableId$1;
2630
+ label: string;
2631
+ text?: string;
2632
+ position?: "below" | "above";
2633
+ nodeIds: StableId$1[];
2634
+ }>, OperationDefinition<"ensureRefBookmark", {
2635
+ blockId: StableId$1;
2636
+ name: string;
2637
+ }>, OperationDefinition<"insertIndexEntry", {
2638
+ runId: StableId$1;
2639
+ entry: string;
2640
+ nodeIds: StableId$1[];
2641
+ }>, OperationDefinition<"insertIndex", {
2642
+ runId: StableId$1;
2643
+ entryCount: number;
2644
+ nodeIds: StableId$1[];
2645
+ }>, OperationDefinition<"refreshIndex", {
2646
+ entryCount: number;
2647
+ nodeIds: StableId$1[];
2648
+ }>, OperationDefinition<"createStyle", {
2649
+ style: StyleSpec;
2650
+ }>, OperationDefinition<"modifyStyle", {
2651
+ styleId: string;
2652
+ patch: StylePatch;
2653
+ }>, OperationDefinition<"deleteStyle", {
2654
+ styleId: string;
2655
+ }>, OperationDefinition<"setNumberingLevel", {
2656
+ blockId: StableId$1;
2657
+ ilvl: number | null;
2658
+ patch: LevelPatch;
2659
+ }>, OperationDefinition<"setNumberingRestart", {
2660
+ blockId: StableId$1;
2661
+ start: number | null;
2662
+ }>, OperationDefinition<"setParagraphBorders", {
2663
+ blockId: StableId$1;
2664
+ patch: ParagraphBordersPatch;
2665
+ } & SuggestablePayload>, OperationDefinition<"setTabStops", {
2666
+ blockId: StableId$1;
2667
+ stops: TabStopSpec[];
2668
+ } & SuggestablePayload>, OperationDefinition<"setTableBorders", {
2669
+ cellParagraphId: StableId$1;
2670
+ scope: "cell" | "table";
2671
+ edges: TableBorderEdge[];
2672
+ border: TableBorderSpec | null;
2673
+ } & SuggestablePayload>, OperationDefinition<"setTableStyle", {
2674
+ cellParagraphId: StableId$1;
2675
+ styleId: string | null;
2676
+ } & SuggestablePayload>, OperationDefinition<"setTableLook", {
2677
+ cellParagraphId: StableId$1;
2678
+ look: Partial<TableLookToggles>;
2679
+ } & SuggestablePayload>, OperationDefinition<"setTableWidth", {
2680
+ cellParagraphId: StableId$1;
2681
+ unit: "pt" | "pct" | "auto";
2682
+ value?: number;
2683
+ } & SuggestablePayload>, OperationDefinition<"setTableColumnWidth", {
2684
+ cellParagraphId: StableId$1;
2685
+ colIdx: number;
2686
+ widthPt: number;
2687
+ } & SuggestablePayload>, OperationDefinition<"setTableLayout", {
2688
+ cellParagraphId: StableId$1;
2689
+ layout: "fixed" | "autofit";
2690
+ renderedWidths?: number[];
2691
+ } & SuggestablePayload>, OperationDefinition<"setTableCellMargins", {
2692
+ cellParagraphId: StableId$1;
2693
+ scope: "cell" | "table";
2694
+ margins: CellMarginsPt | null;
2695
+ } & SuggestablePayload>, OperationDefinition<"setTableHeaderRows", {
2696
+ cellParagraphId: StableId$1;
2697
+ count: number;
2698
+ } & SuggestablePayload>, OperationDefinition<"insertTableFormula", {
2699
+ cellParagraphId: StableId$1;
2700
+ formula: string;
2701
+ numFmt?: string;
2702
+ nodeIds: StableId$1[];
2703
+ }>, OperationDefinition<"sortTableRows", {
2704
+ cellParagraphId: StableId$1;
2705
+ colIdx: number;
2706
+ order: "asc" | "desc";
2707
+ /** "kind" would collide with the intent discriminant, hence "compare". */
2708
+ compare: "text" | "number";
2709
+ hasHeader?: boolean;
2710
+ }>, OperationDefinition<"convertTextToTable", {
2711
+ blockId: StableId$1;
2712
+ moreBlockIds?: StableId$1[];
2713
+ separator: "tab" | "comma";
2714
+ cellCount: number;
2715
+ nodeIds: StableId$1[];
2716
+ }>, OperationDefinition<"convertTableToText", {
2717
+ cellParagraphId: StableId$1;
2718
+ separator: "tab" | "comma";
2719
+ rowCount: number;
2720
+ nodeIds: StableId$1[];
2721
+ }>, OperationDefinition<"insertEndnote", {
2722
+ runId: StableId$1;
2723
+ text: string;
2724
+ nodeIds: StableId$1[];
2725
+ }>, OperationDefinition<"setCrop", {
2726
+ runId: StableId$1;
2727
+ objectIndex?: number;
2728
+ crop: ImageCrop;
2729
+ }>, OperationDefinition<"setModel3DRotation", {
2730
+ runId: StableId$1;
2731
+ objectIndex?: number;
2732
+ rotation: Model3DRotation;
2733
+ }>, OperationDefinition<"setDrawingTextFit", {
2734
+ runId: StableId$1;
2735
+ objectIndex?: number;
2736
+ mode: DrawingTextFitMode;
2737
+ fontScalePct?: number;
2738
+ }>, OperationDefinition<"insertMergeField", {
2739
+ runId: StableId$1;
2740
+ name: string;
2741
+ nodeIds: StableId$1[];
2742
+ }>, OperationDefinition<"insertCitation", {
2743
+ runId: StableId$1;
2744
+ tag: string;
2745
+ nodeIds: StableId$1[];
2746
+ }>, OperationDefinition<"insertBibliography", {
2747
+ runId: StableId$1;
2748
+ entryCount: number;
2749
+ nodeIds: StableId$1[];
2750
+ }>, OperationDefinition<"refreshBibliography", {
2751
+ entryCount: number;
2752
+ nodeIds: StableId$1[];
2753
+ }>, OperationDefinition<"createCitationSource", {
2754
+ source: CitationSourceSpec;
2755
+ }>, OperationDefinition<"editCitationSource", {
2756
+ tag: string;
2757
+ patch: CitationSourcePatch;
2758
+ }>, OperationDefinition<"deleteCitationSource", {
2759
+ tag: string;
2760
+ }>, OperationDefinition<"setCitationStyle", {
2761
+ style: CitationStyle;
2762
+ }>, OperationDefinition<"createBuildingBlock", {
2763
+ name: string;
2764
+ category?: string;
2765
+ blocksXml: string;
2766
+ }>, OperationDefinition<"insertBuildingBlock", {
2767
+ name: string;
2768
+ /** The carried-id budget, computed by the caller from the SAME already-
2769
+ * synced glossary state the apply side reads (buildingBlockNodeCount) —
2770
+ * the insertBibliography entryCount pattern. */
2771
+ blockCount: number;
2772
+ }>, OperationDefinition<"deleteBuildingBlock", {
2773
+ name: string;
2774
+ }>, OperationDefinition<"insertWatermark", {
2775
+ text: string;
2776
+ headerCount: number;
2777
+ diagonal?: boolean;
2778
+ color?: string;
2779
+ opacity?: number;
2780
+ nodeIds: StableId$1[];
2781
+ }>, OperationDefinition<"insertPictureWatermark", {
2782
+ blobSha: string;
2783
+ bytesLen: number;
2784
+ ext: string;
2785
+ iv?: string;
2786
+ naturalWidthPx: number;
2787
+ naturalHeightPx: number;
2788
+ headerCount: number;
2789
+ washout?: boolean;
2790
+ nodeIds: StableId$1[];
2791
+ }>, OperationDefinition<"removeWatermark", NoPayload>, OperationDefinition<"setTitlePage", {
2792
+ enabled: boolean;
2793
+ nodeIds: StableId$1[];
2794
+ }>, OperationDefinition<"setEvenOddHeaders", {
2795
+ enabled: boolean;
2796
+ nodeIds: StableId$1[];
2797
+ }>, OperationDefinition<"setPageNumberFormat", {
2798
+ fmt?: PageNumberFormat | null;
2799
+ start?: number | null;
2800
+ }>, OperationDefinition<"setHyphenation", {
2801
+ auto?: boolean;
2802
+ zonePt?: number | null;
2803
+ noCaps?: boolean;
2804
+ }>, OperationDefinition<"insertPageNumberPosition", {
2805
+ position: PageNumberGalleryPosition;
2806
+ align: PageNumberGalleryAlign;
2807
+ nodeIds: StableId$1[];
2808
+ }>, OperationDefinition<"removePageNumbers", Record<never, never>>, OperationDefinition<"insertHeaderFooterPreset", {
2809
+ hfKind: "header" | "footer";
2810
+ preset: HeaderFooterPreset;
2811
+ nodeIds: StableId$1[];
2812
+ }>, OperationDefinition<"setFootnoteOptions", {
2813
+ fmt?: NoteNumberFormat | null;
2814
+ start?: number | null;
2815
+ restart?: NoteRestart | null;
2816
+ pos?: "pageBottom" | "beneathText" | null;
2817
+ }>, OperationDefinition<"setEndnoteOptions", {
2818
+ fmt?: NoteNumberFormat | null;
2819
+ start?: number | null;
2820
+ restart?: NoteRestart | null;
2821
+ pos?: "sectEnd" | "docEnd" | null;
2822
+ }>];
2823
+ type AnyOperationDefinition = (typeof OPERATIONS)[number];
2824
+ /** Distributes: one body type per registered operation. */
2825
+ type BodyOf<D> = D extends OperationDefinition<infer Kind, infer Payload> ? {
2826
+ kind: Kind;
2827
+ } & Payload : never;
2828
+ type RegisteredOperationKind = AnyOperationDefinition["kind"];
2829
+ /**
2830
+ * The wire body of every registered operation. @wordinweb/collab intersects
2831
+ * this with its IntentBase bookkeeping to form the Intent variants, so the
2832
+ * payload is declared once and the wire shape follows.
2833
+ */
2834
+ type RegisteredOperationBody = BodyOf<AnyOperationDefinition>;
2835
+
1683
2836
  /**
1684
2837
  * Wire intents for replicated editing.
1685
2838
  *
@@ -1694,6 +2847,7 @@ declare class DocxDocument {
1694
2847
  * against everything sequenced in `(base, seq)` before applying and
1695
2848
  * broadcasting the canonical form (doc 03).
1696
2849
  */
2850
+
1697
2851
  type StableId = number;
1698
2852
  /** A caret/endpoint position within a run. */
1699
2853
  interface Position {
@@ -1734,10 +2888,13 @@ interface SuggestRevisionIntent extends IntentBase {
1734
2888
  blockId: StableId;
1735
2889
  glyph: "ins" | "del";
1736
2890
  }[];
1737
- suggest: {
1738
- author: string;
1739
- date: string;
1740
- };
2891
+ suggest: SuggestMeta;
2892
+ }
2893
+ /** Author + date of a tracked change, generated once by the originating
2894
+ * client so every replica writes the same w:author/w:date (rule a above). */
2895
+ interface SuggestMeta {
2896
+ author: string;
2897
+ date: string;
1741
2898
  }
1742
2899
  /** Insert `text` at a position. With `suggest`, the insertion is recorded as
1743
2900
  * a tracked change (w:ins) carrying the author + date (revision tracking /
@@ -1752,6 +2909,37 @@ interface InsertTextIntent extends IntentBase {
1752
2909
  date: string;
1753
2910
  };
1754
2911
  }
2912
+ /**
2913
+ * Insert an inline separator — a soft line break (w:br, Shift+Enter) or a
2914
+ * tab character (w:tab, Tab in a body paragraph) — at a position. The
2915
+ * mutation splits the addressed run's w:t IN PLACE (no new run, every stable
2916
+ * id preserved), and a separator counts ONE unit in the run's wire-offset
2917
+ * basis (core runWireLength), so the transform is exactly an insertText of
2918
+ * length one. With `suggest` the separator is recorded as a w:ins sibling
2919
+ * (insertSuggestedSeparator) like a typed suggestion.
2920
+ */
2921
+ interface InsertSeparatorIntent extends IntentBase {
2922
+ kind: "insertSeparator";
2923
+ at: Position;
2924
+ separator: "br" | "tab";
2925
+ suggest?: SuggestMeta;
2926
+ }
2927
+ /**
2928
+ * Delete the inline separator (w:br / w:tab / w:cr) occupying wire unit
2929
+ * [at.offset, at.offset+1) of the addressed run — insertSeparator's inverse
2930
+ * (a separator-aware Backspace/Delete). The plain mutation removes the
2931
+ * separator element and joins the two w:t halves its insert split, so the
2932
+ * transform is exactly a deleteText of length one in the separator-counting
2933
+ * wire basis. With `suggest` the separator is recorded as a tracked deletion
2934
+ * instead (deleteSuggestedSeparator: a w:del around the separator's own run
2935
+ * slice, the host run splitting like a text strike). A unit that no longer
2936
+ * holds a separator (concurrent edit) is a clean no-op on every replica.
2937
+ */
2938
+ interface DeleteSeparatorIntent extends IntentBase {
2939
+ kind: "deleteSeparator";
2940
+ at: Position;
2941
+ suggest?: SuggestMeta;
2942
+ }
1755
2943
  /** Delete `[start, end)` characters within a single run. */
1756
2944
  interface DeleteTextIntent extends IntentBase {
1757
2945
  kind: "deleteText";
@@ -1793,6 +2981,9 @@ interface FormatRunIntent extends IntentBase {
1793
2981
  /** RunFormatPatch (bold/italic/underline/strike/color/…). Structural shape
1794
2982
  * mirrors @wordinweb/core's RunFormatPatch; carried verbatim. */
1795
2983
  patch: Record<string, unknown>;
2984
+ /** Tracked-change (suggesting) metadata: the run records the properties it
2985
+ * had in a w:rPrChange instead of losing them. Omit for a direct format. */
2986
+ suggest?: SuggestMeta;
1796
2987
  }
1797
2988
  /**
1798
2989
  * Paragraph-level formatting: alignment and/or paragraph style. Block-level —
@@ -1805,17 +2996,26 @@ interface FormatParagraphIntent extends IntentBase {
1805
2996
  align?: "left" | "center" | "right" | "justify";
1806
2997
  /** Paragraph style id; null clears to Normal. Omit to leave unchanged. */
1807
2998
  styleId?: string | null;
2999
+ /** Tracked-change (suggesting) metadata: the paragraph records the
3000
+ * properties it had in a w:pPrChange. Omit for a direct format. */
3001
+ suggest?: SuggestMeta;
1808
3002
  }
1809
3003
  /**
1810
3004
  * Turn a paragraph into a bullet/numbered list item, or clear its list
1811
3005
  * formatting (kind null). Block-level: mutates w:pPr/numbering, preserves the
1812
3006
  * block id, moves no text — transform identity.
3007
+ *
3008
+ * A multi-paragraph selection rides in ONE intent (optional `moreBlockIds`
3009
+ * beyond the addressed paragraph): the single apply mints ONE numbering
3010
+ * definition shared by every target, which is both Word's semantics (one
3011
+ * continuous list) and the only convergent shape — per-paragraph intents
3012
+ * each minted a fresh definition at apply, diverging from the originator's
3013
+ * single shared-definition local mutation.
3014
+ *
3015
+ * REGISTERED: shape and wiring come from the core operation registry (see
3016
+ * RegisteredIntent below). The alias keeps the published type name.
1813
3017
  */
1814
- interface SetListTypeIntent extends IntentBase {
1815
- kind: "setListType";
1816
- blockId: StableId;
1817
- listKind: "bullet" | "number" | null;
1818
- }
3018
+ type SetListTypeIntent = RegisteredIntentOf<"setListType">;
1819
3019
  /**
1820
3020
  * Format a character sub-range of a single run (plan doc 03 F3). The run is
1821
3021
  * split into up to three pieces — before [0,start), middle [start,end)
@@ -1836,19 +3036,23 @@ interface FormatRangeIntent extends IntentBase {
1836
3036
  beforeId?: StableId;
1837
3037
  middleId: StableId;
1838
3038
  afterId?: StableId;
3039
+ /** Tracked-change (suggesting) metadata: the middle piece records the
3040
+ * properties it had in a w:rPrChange. Omit for a direct format. */
3041
+ suggest?: SuggestMeta;
1839
3042
  }
1840
3043
  /**
1841
- * A table operation that does NOT create new tracked nodes (so no carried ids
1842
- * are needed and the transform is identity): delete row/column/table, cell
1843
- * shading, cell vertical align. The target cell is addressed by the stable id
1844
- * of a paragraph inside it. Row/column INSERTION (which creates cells with new
1845
- * paragraphs and runs needing carried ids) is a documented harder extension.
3044
+ * A table operation addressed by the stable id of a paragraph inside the
3045
+ * target cell. Every op is position-stable (no surviving run's offsets move),
3046
+ * so the transform is identity; concurrent edits into removed cells fail
3047
+ * cleanly at apply (retired ids). Ops that create tracked nodes (the inserts,
3048
+ * mergeDown's fresh continuation paragraph, splitCell's new cells) take their
3049
+ * ids from `nodeIds`; ops that remove content prune the retired ids at apply.
1846
3050
  */
1847
3051
  interface TableOpIntent extends IntentBase {
1848
3052
  /** Stable id of a paragraph inside the target cell. */
1849
3053
  cellParagraphId: StableId;
1850
3054
  kind: "tableOp";
1851
- op: "deleteRow" | "deleteCol" | "deleteTable" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | {
3055
+ op: "deleteRow" | "deleteCol" | "deleteTable" | "rowAbove" | "rowBelow" | "colLeft" | "colRight" | "mergeRight" | "mergeDown" | "splitCell" | {
1852
3056
  kind: "cellShading";
1853
3057
  fill: string | null;
1854
3058
  } | {
@@ -1860,10 +3064,18 @@ interface TableOpIntent extends IntentBase {
1860
3064
  xPx: number;
1861
3065
  yPx: number;
1862
3066
  };
1863
- /** For INSERT ops (rowAbove/rowBelow/colLeft/colRight): carried ids for the
1864
- * new tracked nodes (p / r) in document order, so replicas address them
1865
- * alike. */
3067
+ /** For ops that create tracked nodes (rowAbove/rowBelow/colLeft/colRight,
3068
+ * mergeDown, splitCell): carried ids for the new nodes (p / r) in document
3069
+ * order, so replicas address them alike. */
1866
3070
  nodeIds?: StableId[];
3071
+ /**
3072
+ * Tracked-change (suggesting) metadata; see FormatParagraphIntent. Only the
3073
+ * three FORMATTING ops honour it — cellShading and cellVAlign record a
3074
+ * w:tcPrChange, textWrapping a w:tblPrChange. The structural ops have no
3075
+ * tracked form and ignore it, so the surfaces that enforce suggesting mode
3076
+ * refuse those outright rather than send one.
3077
+ */
3078
+ suggest?: SuggestMeta;
1867
3079
  }
1868
3080
  /**
1869
3081
  * Merge a paragraph into its predecessor (Backspace at paragraph start). The
@@ -1875,6 +3087,14 @@ interface MergeParagraphIntent extends IntentBase {
1875
3087
  kind: "mergeParagraph";
1876
3088
  /** The paragraph to merge into the one before it. */
1877
3089
  blockId: StableId;
3090
+ /**
3091
+ * Tracked-change (suggesting) metadata. Word tracks a merge as a DELETED
3092
+ * PARAGRAPH MARK: the pilcrow that separates the two paragraphs — the
3093
+ * PREVIOUS paragraph's mark — gets a w:del in its pPr/rPr, and both
3094
+ * paragraphs stay in place until the reviewer accepts. Omit for a direct
3095
+ * merge.
3096
+ */
3097
+ suggest?: SuggestMeta;
1878
3098
  }
1879
3099
  /**
1880
3100
  * Add a review comment anchored to an entire run. Comment markers
@@ -1970,11 +3190,14 @@ interface InsertMathIntent extends IntentBase {
1970
3190
  mathText: string;
1971
3191
  nodeIds: StableId[];
1972
3192
  }
1973
- /** Insert a shape/textbox drawing at the end of a run (sibling — identity). */
3193
+ /** Insert a shape/textbox drawing at the end of a run (sibling — identity).
3194
+ * `preset` is a legacy named preset (line/verticalLine/rectangle/
3195
+ * roundedRectangle/ellipse/diamond/textBox) or any ST_ShapeType name core's
3196
+ * preset-geometry table knows; validated with isValidShapePreset. */
1974
3197
  interface InsertShapeIntent extends IntentBase {
1975
3198
  kind: "insertShape";
1976
3199
  runId: StableId;
1977
- preset: "line" | "verticalLine" | "rectangle" | "roundedRectangle" | "ellipse" | "diamond" | "textBox";
3200
+ preset: string;
1978
3201
  text?: string;
1979
3202
  nodeIds: StableId[];
1980
3203
  }
@@ -2000,6 +3223,8 @@ interface AdjustIndentIntent extends IntentBase {
2000
3223
  kind: "adjustIndent";
2001
3224
  blockId: StableId;
2002
3225
  direction: 1 | -1;
3226
+ /** Tracked-change (suggesting) metadata; see FormatParagraphIntent. */
3227
+ suggest?: SuggestMeta;
2003
3228
  }
2004
3229
  /** Set paragraph line/before/after spacing. Block-level, identity. */
2005
3230
  interface SetSpacingIntent extends IntentBase {
@@ -2007,6 +3232,8 @@ interface SetSpacingIntent extends IntentBase {
2007
3232
  blockId: StableId;
2008
3233
  /** ParagraphSpacingPatch (before/after/line/lineRule) — carried verbatim. */
2009
3234
  patch: Record<string, unknown>;
3235
+ /** Tracked-change (suggesting) metadata; see FormatParagraphIntent. */
3236
+ suggest?: SuggestMeta;
2010
3237
  }
2011
3238
  /** Insert a page-number field at the end of a run (sibling insertion,
2012
3239
  * identity). Page fields are deterministic (no clock). */
@@ -2050,7 +3277,22 @@ interface InsertBookmarkIntent extends IntentBase {
2050
3277
  runId: StableId;
2051
3278
  name: string;
2052
3279
  }
2053
- type Intent = InsertTextIntent | DeleteTextIntent | SplitParagraphIntent | FormatRunIntent | FormatParagraphIntent | SetListTypeIntent | FormatRangeIntent | TableOpIntent | MergeParagraphIntent | CommentRunIntent | PasteBlocksIntent | InsertImageIntent | SuggestRevisionIntent | InsertBreakIntent | InsertMathIntent | InsertShapeIntent | ReplyCommentIntent | AdjustIndentIntent | SetSpacingIntent | InsertPageFieldIntent | SetLinkIntent | InsertFootnoteIntent | SetDropCapIntent | SetDividerIntent | InsertBookmarkIntent | InsertBlankPageIntent | InsertSectionBreakIntent | InsertCrossRefIntent | InsertCoverPageIntent | SetPageLayoutIntent | SetListLevelIntent | InsertWordArtIntent | InsertChartIntent | InsertSmartArtIntent | SetLineNumberingIntent | InsertDateTimeFieldIntent | InsertFieldIntent | SetDrawingRotationIntent | SetDrawingFillIntent | SetChartDataIntent | SetSmartArtNodeTextIntent | SetDrawingWordArtTextIntent | SetDrawingWordArtStyleIntent | SetDrawingLineStyleIntent | SetImageAltTextIntent | RemoveLinkIntent | SetImageWrapIntent | SetDrawingOrderIntent | SetSmartArtDataIntent | SetSmartArtFillIntent | SetSmartArtTextFormatIntent | SetFloatingPagePositionIntent | ResizeDrawingIntent | ResizeTableColumnIntent | ResizeTableRowIntent | MoveTableIntent | RemoveDrawingIntent | SetMathLinearIntent | DeleteMathIntent | MoveMathIntent | EnsureHeaderFooterIntent | DeleteCommentIntent | InsertBookmarkRangeIntent | ToggleCheckboxIntent | AcceptRevisionIntent | RejectRevisionIntent | AcceptAllRevisionsIntent | RejectAllRevisionsIntent | InsertTableIntent;
3280
+ /**
3281
+ * Intents whose wire shape comes from the core operation registry. One
3282
+ * declaration in @wordinweb/core's edit/registry.ts produces the payload, the
3283
+ * apply, the validation, the carried-id budget, and the agent capability row;
3284
+ * here it just picks up the wire bookkeeping every intent carries.
3285
+ *
3286
+ * The registry admits only id-addressed, position-stable operations with no
3287
+ * wire inverse, so every registered intent's transform is identity and
3288
+ * collaborative undo skips it — see the registry's module comment.
3289
+ */
3290
+ type RegisteredIntent = RegisteredOperationBody & IntentBase;
3291
+ /** One registered intent, by kind. */
3292
+ type RegisteredIntentOf<Kind extends RegisteredOperationKind> = Extract<RegisteredIntent, {
3293
+ kind: Kind;
3294
+ }>;
3295
+ type Intent = InsertTextIntent | InsertSeparatorIntent | DeleteSeparatorIntent | DeleteTextIntent | SplitParagraphIntent | FormatRunIntent | FormatParagraphIntent | SetListTypeIntent | FormatRangeIntent | TableOpIntent | MergeParagraphIntent | CommentRunIntent | PasteBlocksIntent | InsertImageIntent | SuggestRevisionIntent | InsertBreakIntent | InsertMathIntent | InsertShapeIntent | ReplyCommentIntent | AdjustIndentIntent | SetSpacingIntent | InsertPageFieldIntent | SetLinkIntent | InsertFootnoteIntent | SetDropCapIntent | SetDividerIntent | InsertBookmarkIntent | InsertBlankPageIntent | InsertSectionBreakIntent | InsertCrossRefIntent | InsertCoverPageIntent | SetPageLayoutIntent | SetListLevelIntent | InsertWordArtIntent | InsertChartIntent | InsertSmartArtIntent | SetLineNumberingIntent | InsertDateTimeFieldIntent | InsertFieldIntent | SetDrawingRotationIntent | SetDrawingFillIntent | SetChartDataIntent | SetSmartArtNodeTextIntent | SetDrawingWordArtTextIntent | SetDrawingWordArtStyleIntent | SetDrawingLineStyleIntent | SetImageAltTextIntent | RemoveLinkIntent | SetImageWrapIntent | SetDrawingOrderIntent | SetSmartArtDataIntent | SetSmartArtFillIntent | SetSmartArtTextFormatIntent | SetFloatingPagePositionIntent | ResizeDrawingIntent | ResizeTableColumnIntent | MoveTableIntent | RemoveDrawingIntent | SetMathLinearIntent | DeleteMathIntent | MoveMathIntent | EnsureHeaderFooterIntent | DeleteCommentIntent | ResolveCommentIntent | EditCommentIntent | InsertBookmarkRangeIntent | AcceptRevisionIntent | RejectRevisionIntent | AcceptAllRevisionsIntent | RejectAllRevisionsIntent | RegisteredIntent;
2054
3296
  /** Insert a blank page at the end of a run. */
2055
3297
  interface InsertBlankPageIntent extends IntentBase {
2056
3298
  kind: "insertBlankPage";
@@ -2098,22 +3340,33 @@ interface InsertWordArtIntent extends IntentBase {
2098
3340
  kind: "insertWordArt";
2099
3341
  runId: StableId;
2100
3342
  text: string;
2101
- preset: "plain" | "archUp" | "archDown" | "wave" | "chevron";
3343
+ preset: "plain" | "archUp" | "archDown" | "wave" | "chevron" | "circle" | "button" | "chevronDown";
3344
+ /** Gallery style: glyph fill plus optional outline and shadow. */
3345
+ style?: {
3346
+ fill: string;
3347
+ outline?: {
3348
+ color: string;
3349
+ widthPt: number;
3350
+ };
3351
+ shadow?: boolean;
3352
+ };
2102
3353
  nodeIds: StableId[];
2103
3354
  }
2104
- /** Insert a data chart (column/bar/line/pie) at the end of a run. The chart
2105
- * data is carried verbatim; the workbook part is generated deterministically. */
3355
+ /** Insert a data chart at the end of a run. The chart data is carried
3356
+ * verbatim; the workbook part is generated deterministically. */
2106
3357
  interface InsertChartIntent extends IntentBase {
2107
3358
  kind: "insertChart";
2108
3359
  runId: StableId;
2109
3360
  chart: {
2110
- type: "column" | "bar" | "line" | "pie";
3361
+ type: "column" | "bar" | "line" | "pie" | "doughnut" | "area" | "scatter";
2111
3362
  title?: string;
2112
3363
  categories: string[];
2113
3364
  series: {
2114
3365
  name: string;
2115
3366
  values: number[];
2116
3367
  }[];
3368
+ /** How bar/column/area series group; absent = clustered. */
3369
+ grouping?: "clustered" | "stacked" | "percentStacked";
2117
3370
  };
2118
3371
  nodeIds: StableId[];
2119
3372
  }
@@ -2179,15 +3432,7 @@ interface SetDrawingFillIntent extends IntentBase, DrawingTarget {
2179
3432
  interface SetChartDataIntent extends IntentBase, DrawingTarget {
2180
3433
  kind: "setChartData";
2181
3434
  runId: StableId;
2182
- chart: {
2183
- type: "column" | "bar" | "line" | "pie";
2184
- title?: string;
2185
- categories: string[];
2186
- series: {
2187
- name: string;
2188
- values: number[];
2189
- }[];
2190
- };
3435
+ chart: InsertChartIntent["chart"];
2191
3436
  }
2192
3437
  /** Set the text of one node of the SmartArt diagram carried by a run. */
2193
3438
  interface SetSmartArtNodeTextIntent extends IntentBase, DrawingTarget {
@@ -2303,13 +3548,6 @@ interface ResizeTableColumnIntent extends IntentBase {
2303
3548
  deltaPx: number;
2304
3549
  renderedWidths?: number[];
2305
3550
  }
2306
- /** Drag-resize a table row's height (trHeight atLeast). */
2307
- interface ResizeTableRowIntent extends IntentBase {
2308
- kind: "resizeTableRow";
2309
- cellParagraphId: StableId;
2310
- rowIdx: number;
2311
- heightPx: number;
2312
- }
2313
3551
  /** Position a table at page coordinates (converts inline to float). */
2314
3552
  interface MoveTableIntent extends IntentBase {
2315
3553
  kind: "moveTable";
@@ -2324,25 +3562,32 @@ interface RemoveDrawingIntent extends IntentBase, DrawingTarget {
2324
3562
  kind: "removeDrawing";
2325
3563
  runId: StableId;
2326
3564
  }
2327
- /** Replace the equation of the math object in a paragraph (linear syntax).
3565
+ /**
3566
+ * Which equation inside a block a math intent means: its position among the
3567
+ * block's m:oMath elements in document order. Absent means the first one, so
3568
+ * an intent recorded before a block could hold more than one addressable
3569
+ * equation still names what it always named.
3570
+ */
3571
+ interface MathTarget {
3572
+ blockId: StableId;
3573
+ mathIndex?: number;
3574
+ }
3575
+ /** Replace the equation of a math object in a paragraph (linear syntax).
2328
3576
  * Math (m:oMath) lives at paragraph level, so this is block-addressed. */
2329
- interface SetMathLinearIntent extends IntentBase {
3577
+ interface SetMathLinearIntent extends IntentBase, MathTarget {
2330
3578
  kind: "setMathLinear";
2331
- blockId: StableId;
2332
3579
  mathText: string;
2333
3580
  }
2334
- /** Delete the math object in a paragraph. */
2335
- interface DeleteMathIntent extends IntentBase {
3581
+ /** Delete a math object in a paragraph. */
3582
+ interface DeleteMathIntent extends IntentBase, MathTarget {
2336
3583
  kind: "deleteMath";
2337
- blockId: StableId;
2338
3584
  }
2339
3585
  /** Drag-move the equation out of `blockId` to the text position `at`. The
2340
- * equation is addressed like the other math intents (block + firstMathIn); the
3586
+ * equation is addressed like the other math intents (block + mathIndex); the
2341
3587
  * destination is an ordinary wire caret. Dropping mid-text splits the
2342
3588
  * destination run, so the split-off tail run takes a carried id. */
2343
- interface MoveMathIntent extends IntentBase {
3589
+ interface MoveMathIntent extends IntentBase, MathTarget {
2344
3590
  kind: "moveMath";
2345
- blockId: StableId;
2346
3591
  at: Position;
2347
3592
  nodeIds: StableId[];
2348
3593
  }
@@ -2358,11 +3603,36 @@ interface EnsureHeaderFooterIntent extends IntentBase {
2358
3603
  hfKind: "header" | "footer";
2359
3604
  nodeIds: StableId[];
2360
3605
  }
2361
- /** Delete a comment (and its reply thread) by id. */
3606
+ /** Delete a comment (and its reply thread) by id. Addressed with a reply's
3607
+ * id it deletes just that reply — the thread/reply distinction is the id. */
2362
3608
  interface DeleteCommentIntent extends IntentBase {
2363
3609
  kind: "deleteComment";
2364
3610
  commentId: string;
2365
3611
  }
3612
+ /**
3613
+ * Resolve (true) or reopen (false) a comment thread. Addressed like
3614
+ * deleteComment, by the comment's deterministic string id (a reply id
3615
+ * resolves its thread's parent). The mutation writes w15:done on the thread
3616
+ * parent's commentsExtended entry; when the parent's body paragraph carries
3617
+ * no w14:paraId yet, the carried `paraId` candidate is consumed to mint one
3618
+ * (provenance rule a — generated once by the originator, identical XML on
3619
+ * every replica). No document run's text moves — identity transform.
3620
+ */
3621
+ interface ResolveCommentIntent extends IntentBase {
3622
+ kind: "resolveComment";
3623
+ commentId: string;
3624
+ resolved: boolean;
3625
+ /** paraId candidate, consumed only when the thread parent lacks one. */
3626
+ paraId: string;
3627
+ }
3628
+ /** Replace a comment's body text (Word's edit-my-comment). Author, date, id,
3629
+ * anchors and threading stay; deterministic given the carried text — identity
3630
+ * transform, clean no-op for an unknown id or unchanged text. */
3631
+ interface EditCommentIntent extends IntentBase {
3632
+ kind: "editComment";
3633
+ commentId: string;
3634
+ text: string;
3635
+ }
2366
3636
  /** Wrap a sub-range of a run's text in a named bookmark. */
2367
3637
  interface InsertBookmarkRangeIntent extends IntentBase {
2368
3638
  kind: "insertBookmarkRange";
@@ -2371,11 +3641,6 @@ interface InsertBookmarkRangeIntent extends IntentBase {
2371
3641
  start: number;
2372
3642
  end: number;
2373
3643
  }
2374
- /** Toggle the checkbox content control carried by a run. */
2375
- interface ToggleCheckboxIntent extends IntentBase {
2376
- kind: "toggleCheckbox";
2377
- runId: StableId;
2378
- }
2379
3644
  /** Accept one tracked change, addressed by its position in document order
2380
3645
  * (collectRevisions order — deterministic across replicas). */
2381
3646
  interface AcceptRevisionIntent extends IntentBase {
@@ -2387,21 +3652,17 @@ interface RejectRevisionIntent extends IntentBase {
2387
3652
  kind: "rejectRevision";
2388
3653
  index: number;
2389
3654
  }
2390
- /** Accept every tracked change in the document. */
3655
+ /** Accept every tracked change in the document, or only one author's when
3656
+ * `author` is given — a surface that owns some of the revisions must not
3657
+ * resolve the rest. Absent means all, which is what older clients send. */
2391
3658
  interface AcceptAllRevisionsIntent extends IntentBase {
2392
3659
  kind: "acceptAllRevisions";
3660
+ author?: string;
2393
3661
  }
2394
- /** Reject every tracked change in the document. */
3662
+ /** Reject every tracked change, or only one author's. See AcceptAll. */
2395
3663
  interface RejectAllRevisionsIntent extends IntentBase {
2396
3664
  kind: "rejectAllRevisions";
2397
- }
2398
- /** Insert a rows×cols table after the paragraph containing the anchor run. */
2399
- interface InsertTableIntent extends IntentBase {
2400
- kind: "insertTable";
2401
- runId: StableId;
2402
- rows: number;
2403
- cols: number;
2404
- nodeIds: StableId[];
3665
+ author?: string;
2405
3666
  }
2406
3667
  /** An intent minus its wire bookkeeping — distributive over the union so each
2407
3668
  * variant keeps its own fields (a plain Omit<Intent,…> would collapse to the
@@ -2477,11 +3738,8 @@ interface AgentEditCapability {
2477
3738
  required: string[];
2478
3739
  optional?: string[];
2479
3740
  }
2480
- /**
2481
- * The agent-facing coverage map for the complete canonical edit surface.
2482
- * Record<Intent["kind"], ...> makes a new intent fail the agent build until
2483
- * its tool contract is declared here.
2484
- */
3741
+ /** The complete agent-facing coverage map: hand-written rows plus the rows
3742
+ * the core operation registry declares. */
2485
3743
  declare const AGENT_EDIT_CAPABILITIES: Record<Intent["kind"], AgentEditCapability>;
2486
3744
  type JsonSchema$1 = Record<string, unknown>;
2487
3745
  declare function agentOperationSchema(kind: Intent["kind"]): JsonSchema$1;
@@ -2490,6 +3748,15 @@ declare function agentCapabilities(category?: AgentEditCapability["category"], r
2490
3748
  kind: Intent["kind"];
2491
3749
  inputSchema: Record<string, unknown>;
2492
3750
  }>;
3751
+ /**
3752
+ * Collapse every repeated subschema that describes *what to write* into one
3753
+ * `$defs` entry and a `$ref` at each site. Shapes that describe *where to
3754
+ * write* (see `ADDRESSING_PROPERTIES`) and shapes that would cost more as a
3755
+ * reference than as themselves are left alone. The resolved schema is
3756
+ * identical to the input, so no caller and no model behaviour depends on which
3757
+ * form it gets.
3758
+ */
3759
+ declare function hoistRepeatedSubschemas(schema: JsonSchema$1): JsonSchema$1;
2493
3760
 
2494
3761
  type AgentReference = string;
2495
3762
  interface AgentCursor {
@@ -2738,6 +4005,44 @@ interface AgentSpatialResult {
2738
4005
  objects: AgentSpatialObject[];
2739
4006
  overlaps: AgentOverlap[];
2740
4007
  }
4008
+ /** One text-bearing drawing's frame measured against its own laid-out text. */
4009
+ interface AgentDrawingFit {
4010
+ objectRef: AgentReference;
4011
+ page: number;
4012
+ /** The frame the shape draws, px. */
4013
+ boxPx: {
4014
+ w: number;
4015
+ h: number;
4016
+ };
4017
+ /** The extent the text actually laid into, px. */
4018
+ textPx: {
4019
+ w: number;
4020
+ h: number;
4021
+ };
4022
+ /** The text is taller than the box's insets leave room for. */
4023
+ overflow: boolean;
4024
+ /** Lines the box hides because they fall past its bottom. */
4025
+ clippedLines: number;
4026
+ /** The shape's bodyPr autofit mode. Only "resizeShape" makes an overflow
4027
+ * resolve itself: Word paints "shrinkText" at full size and clips it. */
4028
+ autofit: "none" | "resizeShape" | "shrinkText";
4029
+ }
4030
+ interface AgentFitResult {
4031
+ revision: string;
4032
+ layout: {
4033
+ quality: "exact" | "approximate";
4034
+ profile: string;
4035
+ };
4036
+ totalPages: number;
4037
+ /** How full each requested page is: where its lowest body content ends, and
4038
+ * where the body box ends. */
4039
+ pages: Array<{
4040
+ page: number;
4041
+ contentBottomPx: number;
4042
+ pageBottomPx: number;
4043
+ }>;
4044
+ drawings: AgentDrawingFit[];
4045
+ }
2741
4046
  type AgentInspectRequest = {
2742
4047
  kind: "overview";
2743
4048
  } | {
@@ -2767,8 +4072,86 @@ type AgentInspectRequest = {
2767
4072
  count: number;
2768
4073
  };
2769
4074
  includeOverlaps?: boolean;
4075
+ } | {
4076
+ kind: "fit";
4077
+ pages?: {
4078
+ start: number;
4079
+ count: number;
4080
+ };
2770
4081
  };
2771
- type AgentInspectResult = AgentOverview | AgentContextResult | AgentReadResult | AgentSearchResult | AgentObjectResult | AgentSpatialResult;
4082
+ type AgentInspectResult = AgentOverview | AgentContextResult | AgentReadResult | AgentSearchResult | AgentObjectResult | AgentSpatialResult | AgentFitResult;
4083
+ type AgentProjectionMode = "text" | "md" | "outline";
4084
+ /** One run of projected characters that came from one place in the document.
4085
+ * `start`/`end` are columns in the projection line; `wireStart`/`wireEnd` are
4086
+ * offsets in the run's wire space. An editable segment is backed by a `w:t`,
4087
+ * so the two spaces line up one-to-one across it and a patch can address any
4088
+ * column inside it. Everything else is an atom the patch path treats as
4089
+ * opaque. */
4090
+ interface AgentAnchorSegment {
4091
+ start: number;
4092
+ end: number;
4093
+ runRef: AgentReference;
4094
+ wireStart: number;
4095
+ wireEnd: number;
4096
+ editable: boolean;
4097
+ }
4098
+ interface AgentAnchorLine {
4099
+ line: number;
4100
+ role: "paragraph" | "table" | "structure";
4101
+ blockRef?: AgentReference;
4102
+ /** Leading characters of the line that are markdown structure rather than
4103
+ * document text (`## `, `- `, `1. `). Always 0 in `text` mode. */
4104
+ marker: number;
4105
+ editable: boolean;
4106
+ segments: AgentAnchorSegment[];
4107
+ }
4108
+ interface AgentProjectRequest {
4109
+ story?: string;
4110
+ mode?: AgentProjectionMode;
4111
+ cursor?: AgentCursor;
4112
+ maxBlocks?: number;
4113
+ maxCharacters?: number;
4114
+ }
4115
+ interface AgentProjectResult {
4116
+ revision: string;
4117
+ story: string;
4118
+ mode: AgentProjectionMode;
4119
+ text: string;
4120
+ lines: number;
4121
+ window: {
4122
+ cursor: string | null;
4123
+ startBlock: number;
4124
+ endBlock: number;
4125
+ maxBlocks: number;
4126
+ maxCharacters: number;
4127
+ };
4128
+ anchors: AgentAnchorLine[];
4129
+ next?: AgentCursor;
4130
+ truncated: boolean;
4131
+ }
4132
+ interface AgentPatchHunk {
4133
+ startLine: number;
4134
+ endLine: number;
4135
+ newText: string;
4136
+ }
4137
+ interface AgentPatchRequest {
4138
+ revision: string;
4139
+ story?: string;
4140
+ mode?: AgentProjectionMode;
4141
+ cursor?: AgentCursor;
4142
+ maxBlocks?: number;
4143
+ maxCharacters?: number;
4144
+ edits?: AgentPatchHunk[];
4145
+ diff?: string;
4146
+ suggest?: boolean;
4147
+ }
4148
+ interface AgentPatchResult {
4149
+ revision: string;
4150
+ status: "applied" | "submitted";
4151
+ operations: string[];
4152
+ connection?: "local" | "live" | "offline" | "reconnecting";
4153
+ projection: AgentProjectResult;
4154
+ }
2772
4155
  type AgentOperation = Record<string, unknown> & {
2773
4156
  kind: string;
2774
4157
  };
@@ -2838,13 +4221,14 @@ type AgentComposeBlock = {
2838
4221
  } | {
2839
4222
  type: "chart";
2840
4223
  chart: {
2841
- type: "column" | "bar" | "line" | "pie";
4224
+ type: "column" | "bar" | "line" | "pie" | "doughnut" | "area" | "scatter";
2842
4225
  title?: string;
2843
4226
  categories: string[];
2844
4227
  series: Array<{
2845
4228
  name: string;
2846
4229
  values: number[];
2847
4230
  }>;
4231
+ grouping?: "clustered" | "stacked" | "percentStacked";
2848
4232
  };
2849
4233
  widthPx?: number;
2850
4234
  heightPx?: number;
@@ -2872,7 +4256,7 @@ type AgentComposeBlock = {
2872
4256
  };
2873
4257
  } | {
2874
4258
  type: "shape";
2875
- preset: "line" | "verticalLine" | "rectangle" | "roundedRectangle" | "ellipse" | "diamond" | "textBox";
4259
+ preset: string;
2876
4260
  text?: string;
2877
4261
  textStyle?: AgentComposeTextStyle;
2878
4262
  widthPx?: number;
@@ -2983,6 +4367,7 @@ declare class AgentDocument {
2983
4367
  private composeAvailable;
2984
4368
  private readonly listeners;
2985
4369
  private readonly inspectedTargets;
4370
+ private readonly projections;
2986
4371
  private constructor();
2987
4372
  static load(bytes: ArrayBuffer | Uint8Array, options?: {
2988
4373
  provenance?: AgentProvenance;
@@ -2998,13 +4383,50 @@ declare class AgentDocument {
2998
4383
  subscribe(listener: (document: DocxDocument, revision: string) => void): () => void;
2999
4384
  addAsset(bytes: Uint8Array, mediaType: string): string;
3000
4385
  private inspector;
4386
+ /**
4387
+ * Read the document the way its READER reads it, whatever is on screen.
4388
+ *
4389
+ * The model these reads walk is derived per revision view, and markup view
4390
+ * keeps deleted runs in it so a reviewer can see the strike-through. Right
4391
+ * for a screen, wrong for an agent: the AI panel turns suggesting on for its
4392
+ * turn, which forces markup, so a SECOND suggestion projected the pending
4393
+ * insertion and the pending deletion interleaved — "The quick brown fox
4394
+ * leajumps over the lazy dog" for a document that reads "leaps". The model
4395
+ * then either rewrote a string no human had ever seen, or, because deleted
4396
+ * runs are not editable text, got "cannot be rewritten across a non-text
4397
+ * atom" and could not stack a second change at all.
4398
+ *
4399
+ * So every model-derived read runs in final view: insertions are text,
4400
+ * deletions are gone — the document as it will read once the suggestions are
4401
+ * accepted. Only the READS move. The operations they produce address runs by
4402
+ * stable id, at offsets within a run's own text; both are properties of the
4403
+ * XML and mean the same thing in either view, so applying them needs no
4404
+ * switch and the view on screen never flickers.
4405
+ */
4406
+ private inFinalView;
3001
4407
  asset(ref: string): AgentAsset;
3002
4408
  inspect(request: AgentInspectRequest): AgentInspectResult;
4409
+ private inspectFinal;
3003
4410
  private recordInspection;
4411
+ /** Fingerprints are recorded during a final-view read, so they have to be
4412
+ * re-taken in one: compared across views, every block holding a tracked
4413
+ * change reads as concurrently edited and the patch dies as "stale". */
4414
+ private fingerprintsMatch;
3004
4415
  private revisionMatchesEdit;
4416
+ /** Render the document as deterministic text plus the anchor map that owns
4417
+ * the rendered-to-wire translation. Read-only: nothing here mutates. */
4418
+ project(request?: AgentProjectRequest): AgentProjectResult;
4419
+ private projectFinal;
4420
+ patch(request: AgentPatchRequest): Promise<AgentPatchResult>;
4421
+ private patchWindow;
3005
4422
  capabilities(category?: AgentEditCapability["category"], kind?: Intent["kind"]): ReturnType<typeof agentCapabilities>;
3006
4423
  compose(request: AgentComposeRequest): Promise<AgentComposeResult>;
4424
+ private composeDocument;
3007
4425
  edit(request: AgentEditRequest): Promise<AgentEditResult>;
4426
+ /** The transaction itself. patch() and compose() call this rather than
4427
+ * edit(), so each states the rollback in its own caller's terms instead of
4428
+ * telling a patch author to resend "operations" it never sent. */
4429
+ private editTransaction;
3008
4430
  private editLocal;
3009
4431
  private editCollaborative;
3010
4432
  save(): Uint8Array;
@@ -3050,8 +4472,23 @@ declare class LocalDocumentSession implements AgentCollaborativeTarget {
3050
4472
  allocIds: (count: number) => number[];
3051
4473
  subscribe(listener: () => void): () => void;
3052
4474
  takeRenderScope: () => Scope | null;
4475
+ /**
4476
+ * Called immediately before an intent mutates the document.
4477
+ *
4478
+ * A host that also renders this document — the desktop app, whose editor owns
4479
+ * an undo stack — sets this to take a checkpoint, so an edit made by an agent
4480
+ * is reachable with Cmd+Z like any other. Without it the agent's changes are
4481
+ * applied behind the editor's back: undo cannot reverse them, and structural
4482
+ * ones have no tracked form to reject either, leaving no way back.
4483
+ */
4484
+ onBeforeApply: (() => void) | null;
3053
4485
  submit: (operation: IntentBody) => void;
3054
4486
  submitOp: (operation: IntentBody) => void;
4487
+ /** Record a local history undo/redo that mutated the shared doc outside the
4488
+ * intent path (the editor already re-rendered itself). Matches the
4489
+ * pre-applied contract: bump the revision so agent-side caches keyed on it
4490
+ * (projections, inspection fingerprints) never serve the pre-undo tree. */
4491
+ noteHistory: () => void;
3055
4492
  /** Record an operation that DocxView already applied to this same object. */
3056
4493
  submitPreApplied: (operation: IntentBody) => void;
3057
4494
  uploadMedia(bytes: Uint8Array): Promise<{
@@ -3059,6 +4496,15 @@ declare class LocalDocumentSession implements AgentCollaborativeTarget {
3059
4496
  bytesLen: number;
3060
4497
  }>;
3061
4498
  private fullIntent;
4499
+ /**
4500
+ * Fill the part an operation just reserved with the bytes this session is
4501
+ * already holding.
4502
+ *
4503
+ * Keyed on the blobSha the operation carries, not on its kind: the sha IS
4504
+ * the media reservation, and every operation that reserves media carries
4505
+ * one (insertImage, insertPictureWatermark). Naming one kind here left
4506
+ * every later one's picture pending forever.
4507
+ */
3062
4508
  private installUploadedImage;
3063
4509
  }
3064
4510
  interface LocalDocumentViewBinding {
@@ -3072,6 +4518,7 @@ interface LocalDocumentViewBinding {
3072
4518
  blobSha: string;
3073
4519
  bytesLen: number;
3074
4520
  }>;
4521
+ noteHistory(): void;
3075
4522
  takeRenderScope(): {
3076
4523
  kind: "doc";
3077
4524
  } | {
@@ -3085,8 +4532,39 @@ interface LocalDocumentViewBinding {
3085
4532
  }
3086
4533
  declare function localDocumentViewBinding(session: LocalDocumentSession): LocalDocumentViewBinding;
3087
4534
 
4535
+ /** Whether `suggest: true` on this kind records a revision. A kind outside the
4536
+ * set applies outright, so the flag is dropped rather than promised. */
4537
+ declare function isSuggestable(kind: unknown): boolean;
4538
+ /** Whether a tableOp's `op` has a tracked form, so it may run while
4539
+ * suggesting. The structural ops are plain strings and never qualify. */
4540
+ declare function isSuggestableTableOp(op: unknown): boolean;
4541
+
3088
4542
  type JsonSchema = Record<string, unknown>;
3089
4543
  declare const AGENT_COMPOSE_SCHEMA: JsonSchema;
3090
4544
  declare function validateAgentComposeRequest(input: unknown): string | null;
3091
4545
 
3092
- export { AGENT_COMPOSE_SCHEMA, AGENT_EDIT_CAPABILITIES, type AgentAsset, type AgentBlock, type AgentBorder, type AgentCollaborativeTarget, type AgentComponentSummary, type AgentComposeBlock, type AgentComposeCell, type AgentComposeRequest, type AgentComposeResult, type AgentComposeRun, type AgentComposeTextStyle, type AgentContextParagraph, type AgentContextResult, type AgentContextRun, type AgentContextStory, type AgentContextTable, type AgentCursor, AgentDocument, type AgentEditCapability, type AgentEditRequest, type AgentEditResult, type AgentInspectRequest, type AgentInspectResult, type AgentObjectResult, type AgentOperation, type AgentOverlap, type AgentOverview, type AgentPageBorders, type AgentParagraph, type AgentProvenance, type AgentReadResult, type AgentReference, type AgentRun, type AgentSearchResult, type AgentSectionLayout, type AgentSpatialObject, type AgentSpatialResult, type AgentTable, type AgentTool, LocalDocumentSession, type LocalDocumentViewBinding, type OutlineEntry, type SpatialBounds, agentCapabilities, agentOperationSchema, collaborativeAgentTarget, localDocumentViewBinding, validateAgentComposeRequest, validateAgentOperationShape };
4546
+ /**
4547
+ * DocMD: a deterministic text projection of a story, produced in the same pass
4548
+ * as the anchor map that owns the rendered-to-wire offset translation.
4549
+ *
4550
+ * Inspection offsets are rendered text and edit offsets are wire units, and
4551
+ * reconciling the two used to be the caller's problem. Here the two spaces are
4552
+ * derived together: every projected character belongs to exactly one anchor
4553
+ * segment, and a segment is editable only when it came verbatim from one `w:t`
4554
+ * — the one case where a projection column is also a wire offset. Agents read
4555
+ * the text; the segments do the arithmetic.
4556
+ */
4557
+ /** Single-character stand-ins for inline content with no editable text. One
4558
+ * character each, so a projection column always names one whole atom and the
4559
+ * anchor map can mark it opaque without span arithmetic. */
4560
+ declare const DOCMD_ATOMS: {
4561
+ readonly tab: "␉";
4562
+ readonly lineBreak: "␊";
4563
+ readonly pageBreak: "␌";
4564
+ readonly field: "␎";
4565
+ readonly math: "␏";
4566
+ readonly noteReference: "␅";
4567
+ readonly object: "";
4568
+ };
4569
+
4570
+ export { AGENT_COMPOSE_SCHEMA, AGENT_EDIT_CAPABILITIES, type AgentAnchorLine, type AgentAnchorSegment, type AgentAsset, type AgentBlock, type AgentBorder, type AgentCollaborativeTarget, type AgentComponentSummary, type AgentComposeBlock, type AgentComposeCell, type AgentComposeRequest, type AgentComposeResult, type AgentComposeRun, type AgentComposeTextStyle, type AgentContextParagraph, type AgentContextResult, type AgentContextRun, type AgentContextStory, type AgentContextTable, type AgentCursor, AgentDocument, type AgentDrawingFit, type AgentEditCapability, type AgentEditRequest, type AgentEditResult, type AgentFitResult, type AgentInspectRequest, type AgentInspectResult, type AgentObjectResult, type AgentOperation, type AgentOverlap, type AgentOverview, type AgentPageBorders, type AgentParagraph, type AgentPatchHunk, type AgentPatchRequest, type AgentPatchResult, type AgentProjectRequest, type AgentProjectResult, type AgentProjectionMode, type AgentProvenance, type AgentReadResult, type AgentReference, type AgentRun, type AgentSearchResult, type AgentSectionLayout, type AgentSpatialObject, type AgentSpatialResult, type AgentTable, type AgentTool, DOCMD_ATOMS, LocalDocumentSession, type LocalDocumentViewBinding, type OutlineEntry, type SpatialBounds, agentCapabilities, agentOperationSchema, collaborativeAgentTarget, hoistRepeatedSubschemas, isSuggestable, isSuggestableTableOp, localDocumentViewBinding, validateAgentComposeRequest, validateAgentOperationShape };