revise 3.1.7 → 4.0.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +1671 -184
  2. package/FONT-LICENSE-HAN-EXT-B.txt +91 -0
  3. package/FONT-LICENSE-KATEX.txt +95 -0
  4. package/FONT-LICENSE-LIBERATION.txt +102 -0
  5. package/FONT-LICENSE-NOTO-MULTILINGUAL.txt +93 -0
  6. package/FONT-LICENSE-NOTO-SANS-SC.txt +93 -0
  7. package/FONT-LICENSE-NOTO.txt +94 -0
  8. package/FONT-LICENSE-SOURCE-CODE-PRO.txt +94 -0
  9. package/FONT-LICENSE-SOURCE-SERIF-4.txt +93 -0
  10. package/LICENSE +41 -21
  11. package/README.md +32 -119
  12. package/THIRD-PARTY-NOTICES.md +2751 -0
  13. package/assets/historyMaterializeWorker-ZFUHJDWr.js +619 -0
  14. package/chunks/AgentPageRenderer-5mZ6fxqO.js +1 -0
  15. package/chunks/AgentPageRenderer-C3jIBoeM.js +1 -0
  16. package/chunks/AttachmentDocumentImporter-CXkM4VoT.js +1 -0
  17. package/chunks/AttachmentDocumentImporter-Kox5By7a.js +1 -0
  18. package/chunks/ColorParserFull-BKH72fK8.js +446 -0
  19. package/chunks/DocumentScrubber-BxmlzNNz.js +1 -0
  20. package/chunks/DocumentScrubber-wmjRnX7C.js +1 -0
  21. package/chunks/DocxConverter-BH3E7nfQ.js +13 -0
  22. package/chunks/DocxConverter-DEHGCdib.js +13 -0
  23. package/chunks/DocxGraft-BMvTAnGi.js +1 -0
  24. package/chunks/DocxGraft-V2YXiUmK.js +1 -0
  25. package/chunks/FileImporter-CtX8ZPjV.js +1 -0
  26. package/chunks/FileImporter-Da-7eRh3.js +1 -0
  27. package/chunks/OdtConverter-CMkSeU8e.js +6 -0
  28. package/chunks/OdtConverter-DV94rkDL.js +6 -0
  29. package/chunks/OfficeImportShared-CA3dia_A.js +1 -0
  30. package/chunks/OfficeImportShared-hxIa69By.js +1 -0
  31. package/chunks/PdfConverter-B-uRwLux.js +21 -0
  32. package/chunks/PdfConverter-B8J_5yim.js +21 -0
  33. package/chunks/PdfImportService-BjQ4rl-Z.js +2 -0
  34. package/chunks/PdfImportService-RtFCP6hh.js +2 -0
  35. package/chunks/RtfConverter-CFDnUApT.js +15 -0
  36. package/chunks/RtfConverter-CpJGtC5U.js +15 -0
  37. package/chunks/XmlConverter-CQCrgTf7.js +2 -0
  38. package/chunks/XmlConverter-CePTE21k.js +2 -0
  39. package/chunks/__vite-browser-external-l0sNRNKZ.js +0 -0
  40. package/chunks/_revise-sdk-lazy-harfbuzz-X8gnYTZL.js +1 -0
  41. package/chunks/ar-vDYSGTpE.js +13 -0
  42. package/chunks/browser-module-B-uafDG6.js +3 -0
  43. package/chunks/browser-module-jwkhffzv.js +3 -0
  44. package/chunks/bundle.min-DRpfgV69.js +782 -0
  45. package/chunks/de-CWX4cvtt.js +13 -0
  46. package/chunks/es-DoAhvF6_.js +13 -0
  47. package/chunks/fil-DdAeD8Br.js +13 -0
  48. package/chunks/fr-CazsUjNQ.js +13 -0
  49. package/chunks/html2canvas.esm-CntiHiYW.js +997 -0
  50. package/chunks/index-BWdRWxoH.js +1807 -0
  51. package/chunks/index-C7VhCKXe.js +402 -0
  52. package/chunks/index-p6UytRm8.js +402 -0
  53. package/chunks/ja-alh_QHTB.js +13 -0
  54. package/chunks/jspdf.es.min-BuJNZ-oY.js +1882 -0
  55. package/chunks/katex-DWj8TvwO.js +1462 -0
  56. package/chunks/pdf-BLWDCiFF.js +1828 -0
  57. package/chunks/persistInlineDocumentImages-DQj2iaqg.js +1 -0
  58. package/chunks/pseudoLocale-Bkzfsfiw.js +1 -0
  59. package/chunks/pseudoLocale-D-AfwRwa.js +1 -0
  60. package/chunks/tree-sitter-D6zWWUMP.js +4 -0
  61. package/chunks/wasmInline.generated-CBYFkdSM.js +1 -0
  62. package/chunks/web-tree-sitter-BXGZGnNj.js +2 -0
  63. package/chunks/zh-20eXwzFZ.js +13 -0
  64. package/cli-shim.js +34 -0
  65. package/full.js +1 -0
  66. package/index.d.ts +995 -13
  67. package/index.js +1 -31
  68. package/legacy/server.d.ts +19 -19
  69. package/legacy/server.js +39 -23
  70. package/package.json +55 -45
  71. package/serverToolContract.d.ts +420 -0
  72. package/serverToolInputs.generated.d.ts +269 -0
  73. package/style.css +1 -0
  74. package/version.d.ts +4 -0
  75. package/version.js +2 -0
  76. package/agent.d.ts +0 -139
  77. package/chunks/chunk-SMTOJL2X.js +0 -2436
  78. package/chunks/chunk-U5X47PZ6.js +0 -135
  79. package/chunks/chunk-U6YKQBKL.js +0 -15
  80. package/chunks/package-5SHL5FOJ.js +0 -14
  81. package/chunks/render-QD5VWKSV.js +0 -109
  82. package/cli-output.schema.json +0 -2159
  83. package/cli.js +0 -4152
  84. package/document.d.ts +0 -439
  85. package/docx.d.ts +0 -73
  86. package/errors.d.ts +0 -14
  87. package/legacy/editor.d.ts +0 -19
  88. package/legacy/editor.js +0 -16
  89. package/legacy/style.css +0 -2
  90. package/package.d.ts +0 -23
  91. package/render.d.ts +0 -27
package/CHANGELOG.md CHANGED
@@ -1,234 +1,1721 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.0
4
+
5
+ The editor is the `revise` package, released at one version with
6
+ [`@reviseio/cli`](https://www.npmjs.com/package/@reviseio/cli) (the CLI and
7
+ TypeScript library) and `@reviseio/engine`, all built from one commit.
8
+
9
+ ### Added
10
+
11
+ - **Live lists of figures and tables.** `<toc source="captions">` lists
12
+ the document's figure captions with page numbers and stays current as
13
+ captions change; `label="Table"` (or any other label, such as Chart or
14
+ Exhibit, matched literally) collects that kind instead. Appendix and
15
+ supplementary numbers (A.2, S1, B-2) are listed. Word's `TOC \c "Label"`
16
+ field imports as one and exports back as the same field, and the list
17
+ renders in PDF, Markdown, RTF, and plain-text exports.
18
+ - **`join_paragraphs` joins ranges.** Pass
19
+ `ranges: [{ firstId, lastId, separator? }]` (up to 100) to join each run
20
+ of consecutive sibling paragraphs, such as lines pasted from a PDF,
21
+ without retyping the text. Every range is checked first: if any is
22
+ invalid, the call reports every problem and changes nothing. Each joined
23
+ range is one tracked change.
24
+ - **Comment anchors across wrapped lines.** A `leave_comment` anchor, or a
25
+ start/end anchor pair, whose text runs on into the following paragraphs
26
+ is anchored across them, as long as every block it spans has been read.
27
+ It used to fail with "Anchor text was not found". A miss now quotes the
28
+ block's text or names a letter-case difference.
29
+ - **`showImportButton`.** With `onImportFile`, controls whether the ribbon
30
+ shows Import (default true). Hosts that import only into an empty
31
+ document (through `uploadPlaceholder`) or by drop can turn it off.
32
+ - **Per-edge cell borders and padding shorthand.** `style_blocks` on table
33
+ cells takes `borderTop`, `borderRight`, `borderBottom`, and `borderLeft`.
34
+ `none` sets that edge to no border, and `null` clears the setting. CSS
35
+ padding shorthand such as `"7px 9px 7px 0"` is accepted (it was refused
36
+ before).
37
+ - **`style_blocks` `fontVariant`** takes `small-caps` or `normal`.
38
+
39
+ ### Changed
40
+
41
+ - **Install `revise`.** `npm i revise`, and import from `revise`,
42
+ `revise/full`, `revise/version`, and `revise/style.css`. Projects on
43
+ `@reviseio/editor` change the dependency and imports; see
44
+ [upgrading](https://revise.io/developer/docs/editor-sdk/installation#upgrade-from-an-earlier-version).
45
+ - **Server-side peer: `@reviseio/cli`.** The optional peer for server-side
46
+ work (conversion, agent tools over a shared Y.Doc, seeding collaboration
47
+ rooms) is `@reviseio/cli` at the same version.
48
+ - **A `revise` command.** It runs the Revise CLI from `@reviseio/cli`: the
49
+ installed copy, or `npx @reviseio/cli` at the same version.
50
+ - **`agent.run()` during a run waits its turn.** A second call while a
51
+ run was in progress used to return at once without running. It now
52
+ starts once the current run has finished, including a run that is still
53
+ ending after an error or `cancel()`.
54
+ - **New table rows and columns match their neighbors.** They take the
55
+ adjacent cell's borders, padding, shading, and vertical alignment. A row
56
+ added under a shaded header row takes the body rows' formatting, and a
57
+ row added to a table with alternating row shading continues the pattern.
58
+ This applies to the editor's table commands and to `insert_table_row` and
59
+ `insert_table_column`.
60
+ - **`replace_block` keeps paragraph layout.** A replacement paragraph keeps
61
+ the replaced paragraph's alignment, indents, spacing, line height, named
62
+ style, and text direction unless its HTML sets them. An explicit value,
63
+ including `line-height: normal` or `data-style-id=""`, still changes it.
64
+ - **A `replace` find may span paragraphs.** A plain-text `find` containing
65
+ line breaks can match the target block and the paragraphs right after
66
+ it. Each replacement line goes into its own block, and text outside the
67
+ match stays where it was. A miss explains the rule.
68
+ - **`join_paragraphs` keeps line-end hyphens.** Without a `separator`, a
69
+ line ending in a hyphen followed by a lowercase word joins with no space
70
+ ("exam-" + "ple" gives "exam-ple"). Other boundaries still get a space.
71
+ - **`remove_blocks` needs no read for page breaks and empty paragraphs.**
72
+ Section breaks and empty paragraphs that carry formatting (horizontal
73
+ rules, for example) still do.
74
+ - **Empty numbered list items show their number** in tool HTML
75
+ (`data-marker`).
76
+ - **The word count shows pages and the selection.** The figures under the
77
+ word count on the Tools tab show pages instead of characters (no page
78
+ count in pageless documents). With text selected they read "N of M
79
+ words" and "N of M pages". The selection count reads pending changes the
80
+ same way the total does, so selecting everything matches the total.
81
+ - **The change at the caret stands out** with
82
+ `settings.trackedChanges.markupStyle: "word"`. The tracked change under
83
+ the caret, or the one Review navigation is on, gets a faint red
84
+ highlight.
85
+ - **The ribbon keeps Export longest.** As the editor narrows, the full
86
+ ribbon first reduces cut, copy, and paste to undo and redo, and the
87
+ compact ribbon drops lists, then headings. Export and Import stay until
88
+ only undo, redo, and the font controls are left. The compact ribbon shows
89
+ Insert when there is room.
90
+ - **Clearer tool errors.** A negative `leftIndent` explains how to make a
91
+ hanging indent, and `leftIndent` or `firstLineIndent` on a list item
92
+ points to `indentLevel`. An `edit_table_cells` target inside a merged
93
+ cell names the merged cell's `row_id` and column. A delegated agent's
94
+ `move_blocks` refused only because of its own pending formatting says to
95
+ roll that back, move, and reformat.
96
+ - **Delegated agent: whole-document reviews are held to coverage.** A
97
+ review, audit, or summary that declares the whole document as its scope
98
+ is sent back to the ranges it skipped, as edits already were. A finish
99
+ reported as incomplete is not. A finish whose only edit is page setup on
100
+ a document the agent hasn't read is asked once to confirm that page setup
101
+ was the whole task.
102
+ - **Delegated agent: searches return up to 200 matches per page** (was 25).
103
+ The `search_document` default for `tools.execute` is unchanged.
104
+ - **Delegated agent: `cancel()` keeps the reasoning so far.** The next
105
+ `agent.run()` continues from the model's reasoning in the turns that
106
+ finished instead of starting without it.
107
+ - **Delegated agent: long conversations reuse the prompt cache.** Earlier
108
+ tool results and images are no longer trimmed from the history on each
109
+ request. The history is summarized only near the model's context budget.
110
+ - **Delegated agent: `render_document_pages` with placeholders** returns
111
+ the pages and marks the images and formulas it couldn't draw
112
+ (`visualVerification: "incomplete"`). It used to refuse every page.
113
+
114
+ ### Fixed
115
+
116
+ - **Footnotes and endnotes in suggesting mode stay with their references.**
117
+ A later edit to a sentence holding a pending note's reference used to
118
+ recreate the reference under the new suggestion or drop it, and rejecting
119
+ either change left a note with no reference. Now the paragraph is edited
120
+ around the reference, deletions over it are layered on top, and
121
+ formatting never moves it. An edit that would rebuild the block (changing
122
+ its type, splitting or joining it, or adding or removing list items
123
+ around it) fails with `pending_footnote_reference` and changes nothing.
124
+ - **Pending notes are credited to the right author.** A person's deletion,
125
+ or a note reference they type, inside an agent's pending text is credited
126
+ to the person, not to the agent's request. A note the agent writes into a
127
+ block it replaces no longer stops that block from being rejected.
128
+ - **Pending footnotes from Word.** A footnote or endnote reference inside a
129
+ tracked insertion or deletion imports with its note as part of the same
130
+ pending change, so accepting or rejecting settles both.
131
+ - **Footnote numbers with collaborators and undo.** Removing a note while a
132
+ collaborator renumbers no longer brings it back. Numbers left stale by an
133
+ undo are corrected on the next edit by any peer that can write, and undo
134
+ or redo of a removed note keeps its reference. A collaborator's typing no
135
+ longer makes every peer scan every paragraph of a long document, and two
136
+ peers renumbering at once no longer produce wrong numbers.
137
+ - **Viewers no longer write to the document when they open it.** In
138
+ `viewing` mode the editor applied legacy-format migrations and footnote
139
+ repairs to the shared Y.Doc, where a sync server rejected them and the
140
+ viewer's copy drifted. A viewer now shows a legacy document as it looks
141
+ after migration, without writing. The migrations run once the session
142
+ gets write access.
143
+ - **`replace` no longer rewrites similar paragraphs next to an exact
144
+ match.** In a table, list, or other container, a `find` that matches one
145
+ paragraph exactly no longer also fuzzy-matches near-identical paragraphs
146
+ beside it ("Paragraph 9 opens…" no longer matches every "Paragraph N
147
+ opens…"). `replace_all` never fuzzy-matches.
148
+ - **Fewer unnecessary "not fully read" refusals on tables.** Inserting a
149
+ block before or after a partly read table, and an exact-text `replace`
150
+ inside one (including `occurrence: "all"` and batches spanning several
151
+ tables), no longer require reading the whole table. Whole-block and
152
+ whole-cell edits still do.
153
+ - **`th` in `style_blocks` selectors** matches only the header row of a
154
+ table that has one. It used to match every body cell in that column.
155
+ - **The agent's own edits no longer look like someone else's.** After a
156
+ `style_blocks` call that restyled many blocks, editing one of them no
157
+ longer fails as "edited after you last read it". A block that is really
158
+ stale fails with the retryable `target_stale`. The agent's own edits no
159
+ longer invalidate its other search results, and cells of a row or column
160
+ it inserted as a pending change are no longer refused (or skipped while
161
+ reporting success) by `edit_table_cells`.
162
+ - **Images in `replace_block`.** An image can be replaced with text,
163
+ including when it is the document's only block (it failed with "not a
164
+ directly editable text block"). Replacing an image keeps the referenced
165
+ image's settings, CSS width and height in px set its size, and the result
166
+ names CSS that images ignore. It used to fall back to 200×200 and report
167
+ success.
168
+ - **A `replace` that matches an image's alt text** fails and says to use
169
+ `replace_block` instead of reporting success without changing anything.
170
+ - **`style_blocks` `letterSpacing: "normal"`** means no extra spacing. It
171
+ was rejected as not a number.
172
+ - **Web-search citation markers** that some OpenAI models emit are removed
173
+ from tool arguments, so they no longer show up as boxes in text,
174
+ footnotes, or comments.
175
+ - **PDF exports open in strict PDF readers.** Embedded TrueType fonts get
176
+ spec-conformant font dictionaries (Identity ordering, a unique subset name
177
+ per face, correctly scaled cap height, and correct italic flags). Pages
178
+ look the same.
179
+ - **Pasting a table with an empty line before or after it**, such as one
180
+ copied from Google Docs, pastes it. It used to do nothing.
181
+ - **Selection observers** no longer log "The selection endpoints no longer
182
+ exist" when a change removes the blocks holding the caret (an import into
183
+ the whole document, or a collaborator deleting them). The selection
184
+ snapshot is empty until the caret is back in the document.
185
+ - **Ribbon menus** no longer overflow their bounds in hosts without a global
186
+ `box-sizing` reset.
187
+ - **Delegated agent: a stalled model stream no longer hangs the run.** A
188
+ turn that receives nothing for five minutes is retried once. A second
189
+ stall in the same request ends the run with an error.
190
+ - **Delegated agent: whole-document coverage.** The coverage check credits
191
+ every range the request read, including reads that were trimmed or
192
+ repeated, reads from before a pause, and what a stopped request read
193
+ before the next one. A short document laid out as a table no longer lets
194
+ the agent stop as "incomplete" without trying, and the agent is sent back
195
+ at most once per blocker.
196
+ - **Delegated agent: edits outside the user's selection** are no longer
197
+ refused.
198
+ - **Delegated agent: removals after a clarifying question.** Blocks the
199
+ agent read before asking can be removed in the answer's request without
200
+ reading them again, if nobody has changed them since.
201
+ - **Delegated agent: page renders in a narrow editor** use the document's
202
+ page layout. On phone-width editors, a multi-page document rendered as
203
+ one long page.
204
+ - **Delegated agent: finishing with `completed_plan_steps` and no plan**
205
+ creates the plan instead of failing.
206
+
207
+ ### Security
208
+
209
+ - **jsPDF 4.2.1.** The bundled PDF writer moves from jsPDF 3.0.1 to a fork
210
+ of 4.2.1, which clears the npm advisories filed against 3.0.1, including
211
+ two critical ones. The fork leaves out `html()` and `addSvgAsImage()`,
212
+ which Revise does not use. THIRD-PARTY-NOTICES.md now lists jsPDF and the
213
+ packages it inlines (fflate, fast-png, pako, iobuffer, Babel helpers).
214
+
3
215
  ## 3.1.7
4
216
 
5
- Released with `@reviseio/editor` 3.1.7, the editor's first release in
6
- lockstep with revise: one version and one build for all three packages. A
7
- Y.Doc or .docx moves between the editor and revise unchanged.
217
+ From this release the editor, the CLI and library, and `@reviseio/engine`
218
+ share one version, built from one commit.
219
+
220
+ ### Removed
221
+
222
+ - **`@reviseio/editor/server`.** Server-side work moved to
223
+ [`revise`](https://www.npmjs.com/package/revise), the MIT CLI and
224
+ TypeScript library built from the same engine and released with this
225
+ version. It covers everything `/server` did:
226
+
227
+ | `@reviseio/editor/server` | `revise` |
228
+ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
229
+ | `createServerDocumentSession(ydoc)` | `ReviseDocument.fromYDoc(ydoc)`, then `doc.tools` |
230
+ | `parseDocument`, `documentToDocx`, `fileToYDoc` | `ReviseDocument.open(file)`, `doc.export()`, `doc.ydoc` |
231
+ | `exportDocument(room, { mode })`, `ydocToDocx(room)` | `ReviseDocument.fromYDoc(room)`, then `doc.export({ format, mode })` |
232
+ | `seedYDocFromFile(room, bytes, filename)` | `seedYDoc(room, { bytes, filename })` |
233
+ | `encodeYDoc`, `decodeYDoc` | Y.js itself: `Y.encodeStateAsUpdate(doc.ydoc)`; `ReviseDocument.restore(update)` opens a bare update |
234
+
235
+ Documents move between the two unchanged: a Y.Doc the editor edits is a
236
+ Y.Doc `revise` opens, and the reverse. Two differences when porting:
237
+ `revise` methods are async (await them), and tools return
238
+ `{ ok, value | error }` instead of throwing; `doc.export()` returns
239
+ `{ bytes, … }`. `doc.snapshot()` is `revise`'s own storage format, not a
240
+ Y.js update: keep `Y.encodeStateAsUpdate` for anything that speaks Y.js.
241
+
242
+ ### Added
243
+
244
+ - **`uploadPlaceholder`.** With `onImportFile`, an empty document shows
245
+ "Type or paste your text or [Upload] a document" until something is typed
246
+ or pasted. Upload opens a file picker for the same formats as Import and
247
+ hands the file to `onImportFile`. Off by default, and never shown in a
248
+ read-only editor.
249
+ - **Markdown shortcuts while typing.** `#` through `######` and a space at
250
+ the start of a paragraph make it a heading. Typing the closing delimiter of
251
+ `**bold**`, `__bold__`, `*italic*`, `_italic_`, or `` `code` `` formats the
252
+ text and removes the markers. Only keyboard typing converts (paste and
253
+ agent edits don't), never in suggesting mode or inside code, and one undo
254
+ restores the literal text. Like smart quotes, they're on in every editor;
255
+ there is no prop to turn them off yet.
256
+ - **Failed tool results carry `details`** when the tool reported more than
257
+ its message, for example `edit_table_cells`' per-cell `errors` and the
258
+ `recovery_read` that fixes them (`ReviseToolFailure.details`, also on a
259
+ thrown `ReviseToolError`'s `failure`).
260
+
261
+ ### Changed
262
+
263
+ - **`revise` is an optional peer dependency** at the same version. Install
264
+ it for server-side work; a browser-only host doesn't need it. `jsdom` is
265
+ no longer a peer of this package (`revise` brings it).
266
+ - **`remove_blocks` accepts up to 200 ids** per call (was 50). A larger
267
+ batch fails without removing anything and points to `search_result_id`.
268
+ - **`search_document` doesn't page through empty paragraphs.** When every
269
+ match is an empty paragraph, asking for a later page fails and points to
270
+ acting on all of them at once with `search_result_id`.
271
+ - **`insert_table_row` matches its neighbors.** Text in a new row takes the
272
+ paragraph spacing, alignment, font, size, and color of the reference row's
273
+ cell in the same column wherever the HTML leaves them unset. Bold and
274
+ italic are not copied (the reference is often a totals row).
275
+ - **`<del>` in tool HTML** is strikethrough. A `<del data-change-id>` (how
276
+ `revise` shows a tracked deletion) is left out, so HTML copied from a
277
+ tracked read edits the text as it reads with changes accepted.
278
+ - **The delegated agent on long documents.** `agent.run()` and comment
279
+ agents keep long requests within each model's context budget: earlier
280
+ document snapshots leave the conversation and the latest read window is
281
+ sent again. When a document-wide edit leaves thousands of blocks pending,
282
+ the document overview lists a sample of them with the total instead of
283
+ every one. An agent that stops "incomplete" with budget left and nothing
284
+ blocking it is sent back to work, and one that finishes a task it declared
285
+ whole-document after reading under 90% of the document is sent back to the
286
+ ranges it skipped. A request restarted after a reload keeps credit for the
287
+ edits its first attempt made.
288
+
289
+ ### Fixed
290
+
291
+ - **Word-numbered headings stay headings.** Word often numbers clause
292
+ headings ("8.1 Cap on liability") through its heading styles, so they
293
+ import as list items, and their heading level was dropped. They keep it
294
+ now: `measure_document` and the delegated agent count them as sections,
295
+ titled with their number, tool HTML marks them `data-heading`, and
296
+ Markdown export writes them as `## 8.1 Cap on liability`. A paragraph whose
297
+ .docx sets `numId` 0 is no longer numbered by its style.
298
+ - **Markdown export numbers nested lists per level.** An item under "8." is
299
+ "1.", not "9.".
300
+ - **Tracked changes in headers and footers** import from .docx as pending
301
+ changes (they were silently accepted) and export as Word revisions (the old
302
+ and new text were both written, side by side).
303
+ - **Exporting an edited Word file no longer restyles it.** A file whose
304
+ package declares no document defaults exported with 12pt ones, so text that
305
+ inherits its size grew from Word's 10pt to 12pt, and runs that inherit
306
+ Word's default font were written back as explicit Arial. Both now export as
307
+ the original had them.
308
+ - **`set_page_layout` page numbers next to an authored header or footer.**
309
+ When the requested header or footer already has text, the number goes into
310
+ its empty left or right zone (a running head keeps its text and gains the
311
+ number), and the result says where the number is or why it could not be
312
+ placed. It used to report success with no number shown. The `apa7` preset's
313
+ page numbers work the same way; any existing header used to hide them.
314
+
315
+ ## 2.3.2
316
+
317
+ ### Fixed
318
+
319
+ - **Reordering a list** with `replace_block` reported success without
320
+ reordering, and rejecting it after a .docx round trip could duplicate an
321
+ item.
322
+ - **Hyperlinks across a .docx round trip:** tracked changes that add, remove,
323
+ or retarget a link in a list item (including lists in table cells) are
324
+ saved as revisions, so accepting or rejecting them after reopening gives
325
+ the same result as in the editor. A link removed in direct mode stays
326
+ removed when another author has a pending change on it, and a tracked
327
+ removal of a linked list item restores the whole link on reject.
328
+ - **Spacing and list levels across a .docx round trip:** tracked paragraph
329
+ spacing changes, including in list items and table cells, and tracked list
330
+ indent-level changes are saved as revisions, so rejecting them after
331
+ reopening restores the original. Deciding a reopened spacing change no
332
+ longer moves a nested list item to the top level.
333
+ - **Footnotes and table cells across a .docx round trip:** tracked paragraph
334
+ splits and joins in footnotes and table cells are saved as revisions; a
335
+ joined footnote stays joined after accepting, and rejecting no longer
336
+ leaves an extra empty paragraph. Accepting a reopened deletion of a list
337
+ item in a table cell no longer leaves an empty item.
338
+
339
+ ## 2.3.1
340
+
341
+ ### Fixed
342
+
343
+ Agent edits (`tools.call`, `tools.execute`, a delegated `agent.run()`, and
344
+ `@reviseio/editor/server` sessions) no longer change other people's pending
345
+ tracked changes. Before, an edit on or next to content that held someone
346
+ else's suggestions could silently accept them (with `directMode`) or re-create
347
+ them under the editing agent's name and today's date.
348
+
349
+ - **Paragraphs and list items** with pending changes: only the edit itself is
350
+ applied; existing suggestions keep their ids, authors, and dates. This
351
+ covers replacing text, formatting (`style_blocks`, `clear_formatting`),
352
+ appending, splitting, joining, inserting next to them, and item spacing and
353
+ indents.
354
+ - **Tables:** editing one cell changes only that cell. Inserting or removing
355
+ rows and columns keeps the other cells' suggestions.
356
+ - **New refusals instead of silent loss.** A few structural edits can't yet
357
+ keep existing suggestions, so they now fail with a clear error and change
358
+ nothing: `pending_table_changes` (row/column changes or merges on a table
359
+ that already has a pending row or column change or merged cells) and
360
+ `pending_list_changes` (converting a list's type, reordering, or other
361
+ list-level changes while the list holds pending changes). Resolve the
362
+ pending changes first, or edit the text directly.
363
+ - **Rejecting a format change after a .docx round trip** keeps footnote
364
+ references, comment anchors, fields, and hyperlinks. A rejected tracked
365
+ format change could delete a footnote's text.
366
+ - **DOCX export:** imported revision ids stay stable when new suggestions are
367
+ added; deletions over another author's insertion round-trip; replaced
368
+ paragraphs have no stray space after accept or reject in Word; suggestions
369
+ carry their author and date (some were written as "Anonymous"); deleted
370
+ list items accept cleanly after reopening; deleted links restore on reject.
371
+ - **DOCX import:** tracked insertions and deletions inside hyperlinks are
372
+ read; a list item that is wholly inserted or deleted imports as one
373
+ revision.
374
+ - `insert_footnote` works in paragraphs that have pending changes.
375
+ - Removing a table cell's only paragraph empties it instead of leaving a
376
+ change that can't be accepted.
377
+
378
+ ## 2.3.0
379
+
380
+ ### Added
381
+
382
+ - **`toolbarMode="compact"`.** The everyday part of the ribbon, centered,
383
+ for narrow fixed-width hosts (about 760px): undo and redo, font, size,
384
+ styles, paragraph, links, indents, lists, Find, and Export. The clipboard,
385
+ Insert, and Print are left out.
386
+ - **`toolbarMode="floating"`.** The full ribbon as a centered card over the
387
+ canvas, the way the Revise app shows it.
388
+ - **`onImportFile`.** Shows Import before Export in the ribbon (a file picker
389
+ for DOCX, ODT, RTF, Markdown, HTML, text, and XML) and accepts files
390
+ dropped anywhere on the editor, with a "Drop to import" overlay. Image
391
+ drops still insert images. The host receives the file and decides what
392
+ importing means.
393
+ - **Header and footer images.** Logos in Word headers and footers now show
394
+ on the page and in PDF export. They were kept for DOCX round trips but
395
+ never drawn. Images are scaled down to fit the margin band and never
396
+ overlap body text. `set_header_footer` takes an `image` (`image_id` of an
397
+ image already in the document, with `zone`, `alt`, `width`, and `height`)
398
+ and a one-based `sectionIndex` to edit one section's own header or footer.
399
+ Concurrent edits to different bands' images merge instead of overwriting
400
+ each other. DOCX export keeps the logo's alignment. It turns on Word's
401
+ first-page or odd/even headers when a logo needs them, and leaves a logo
402
+ out of sections whose margin is too small to show it.
403
+ - **`@reviseio/editor/server`: `agentName`.**
404
+ `createServerDocumentSession({ agentName })` sets the author on the
405
+ suggestions and comments the session's tools create, which DOCX export
406
+ writes as `w:author`. Defaults to "Revise Agent".
407
+ - **The delegated agent can move any block** as one tracked move: images,
408
+ code, equations, horizontal rules, page breaks, and tables of contents as
409
+ well as paragraphs, lists, and tables. Section breaks are still refused.
8
410
 
9
411
  ### Changed
10
412
 
11
- - **`remove_blocks` takes up to 200 ids** (was 50). Past the limit it removes
12
- nothing and says how to proceed: pass a search's `search_result_id` to
13
- remove every match, or send the ids in batches.
413
+ - **Import paths.** `revise/editor` → `@reviseio/editor`,
414
+ `revise/editor/full` → `@reviseio/editor/full`, `revise/server` →
415
+ `@reviseio/editor/server`, `revise/style.css` →
416
+ `@reviseio/editor/style.css`, and the build identity →
417
+ `@reviseio/editor/version`. The editor, license, and API are unchanged. The
418
+ docs moved to
419
+ [revise.io/developer/docs](https://revise.io/developer/docs/editor-sdk/introduction).
420
+ - **`replace_block` and `remove_blocks` name a range by its last block.**
421
+ `end_id` (inclusive, same container as `id`) replaces `count` in the tool
422
+ definitions and in `ReviseToolInputMap`. Calls with `count` still run, but
423
+ TypeScript callers that pass it need `end_id`. A reversed, unknown, or
424
+ cross-container range fails with `invalid_block_range` before anything
425
+ changes.
426
+ - **`remove_table_rows` replaces `remove_table_row`.** It removes one or more
427
+ rows per call, named by stable row ID (`rowIds`, a string or an array).
428
+ Rows the agent read stay removable after other rows change, without
429
+ reading the table again. `remove_table_row` with `{ tableId, rowIndex }`
430
+ is still accepted.
431
+ - **`read_table` `mode: "cell_text"` pages list their nested blocks**
432
+ (`blocks`: block ID and text offset), and each nested block's text opens
433
+ with an inline `[[block_id]]` marker. Text inside an oversized cell can be
434
+ read with `read_specific_blocks` and edited. A `replace` aimed at a table,
435
+ row, or cell edits the one nested block that contains the text.
436
+ - **`set_header_footer` reports what actually changed.** `clear: true`
437
+ without `slot` or `sectionIndex` removes that side from every page and
438
+ section. A call that changes nothing fails with "No changes detected" and
439
+ the current header/footer listing. An unknown `slot` is an error instead
440
+ of widening a clear. Clearing the first-page or even-page slot while the
441
+ document-wide footer shows there leaves an empty slot that hides it, as in
442
+ Word. `search_document` also matches header and footer text.
443
+ - **Mutation tools refuse empty arrays** (`content`, `replacements`,
444
+ `cells`, `ids`, `rowIds`, style `attrs` or `selectors`) before changing
445
+ anything, and name the tool that fits instead. The definitions mark these
446
+ `minItems: 1`. Empty table-insert content still inserts empty cells.
447
+ - **Edits next to an unresolved paragraph split or merge are refused** with
448
+ `pending_paragraph_boundary`: accept or reject the split first. Such edits
449
+ used to lose or duplicate text on review.
450
+ - **`style_blocks` headings take the document's heading style.** In an
451
+ imported Word document, a paragraph made a heading gets the heading
452
+ style's spacing and run formatting, and exports like the document's other
453
+ headings.
454
+ - **Agent-inserted content follows the surrounding font.** Inserted tables
455
+ take the font and body size at the insertion point. One `insert_block`
456
+ call uses one font for all its pieces. Rows and columns added by
457
+ `insert_table_row` and `insert_table_column` keep the table's font. A
458
+ heading's size no longer carries into paragraphs inserted after it. Cells
459
+ holding only inline markup (`<td><b>Total</b></td>`) keep their
460
+ formatting. Tables inserted from the editor take the caret's font.
461
+ - **DOCX export keeps more of the original file.** Untouched table rows,
462
+ cells, and list items are written as the original bytes when a neighbor
463
+ changes. Paragraphs with only text edits keep their original paragraph
464
+ properties. The original `styles.xml` is kept, with only the missing style
465
+ definitions added. Opening a document with page numbers no longer forces
466
+ headers, footers, and styles to be regenerated. In
467
+ `@reviseio/editor/server`, `exportDocument(room, { mode: "final" })` to
468
+ .docx keeps untouched content as the original bytes too.
469
+ - **The delegated agent** (`agent.run()` and comment agents) sees the
470
+ document's headers and footers. It stays inside a locked user selection
471
+ unless asked to go wider. It may re-read blocks it has already read. It
472
+ puts content asked to be added into the document rather than only in
473
+ chat, and it no longer finishes before results it asked for arrive. With
474
+ Anthropic models, requests that follow edits keep the prompt cache.
14
475
 
15
476
  ### Fixed
16
477
 
17
- - **Page numbers next to an existing header or footer.** `set_page_layout`
18
- with a page-number position, or a preset that numbers pages (APA puts them
19
- top right), used to report success while a hand-authored header or footer
20
- kept the number from appearing. The number now goes into that header's or
21
- footer's empty zone at the requested side, in the authored text's font. When
22
- the zone already holds text or the header already shows a page number, the
23
- result says so and lists the headers and footers instead of claiming the
24
- layout changed.
25
- - **A `replace` whose `find` and `replace` are identical** fails with an error
26
- that says so, instead of the generic "no changes detected".
478
+ - **Comment cards sit beside the page**, as in the Revise app, instead of
479
+ at the far right edge of a wide editor.
480
+ - **The ribbon stays centered on the pages** when the comments margin moves
481
+ them aside, as far as its width allows.
482
+ - **Add Comment and Toggle Comments** in the Review ribbon work. They were
483
+ always disabled.
484
+ - **Find shows in the native ribbon.** It was hidden whenever Dictate was,
485
+ which the SDK always hides.
486
+ - **The ribbon keeps text color and the styling menu down to 352px**, where
487
+ they were dropped below 430px.
488
+ - **The selection stays visible, dimmed, when focus leaves the editor**, for
489
+ example to a chat input in the host page, instead of disappearing.
490
+ - **Copy and Cut work in iframes that deny clipboard access** (no
491
+ `clipboard-write` permission).
492
+ - **Agent avatars on suggestion cards load**, where they used to resolve
493
+ against the host page's origin and show a generic avatar.
494
+ - **Hovering Accept all or Reject all previews the decided document.** Blocks
495
+ the decision removes, such as a moved table's source, are hidden, while
496
+ edited code and math blocks stay. Typing ends the preview, so keys never
497
+ edit a hidden block.
498
+ - **Word redlines with inserted or deleted paragraphs accept and reject
499
+ fully.** Consecutive paragraph-mark revisions used to overwrite each
500
+ other, so rejecting inserted clauses left them in place and accepting
501
+ could leave an empty paragraph. Rejecting a split keeps the paragraph's
502
+ current text, formatting, and pending revisions. Settling a
503
+ paragraph-formatting change no longer undoes later inline decisions.
504
+ Accept all and Reject all finish in one call when one decision uncovers
505
+ another.
506
+ - **Tracked table changes export to Word as revisions.** A suggested row
507
+ insertion, alone or combined with cell edits, is a Word row revision with
508
+ attributed inline cell changes instead of an untracked table. A
509
+ repeating header row survives a tracked deletion of the first row.
510
+ - **Moves of images, code, equations, rules, page breaks, and tables of
511
+ contents export once** to DOCX, not as two copies. Accepting or rejecting
512
+ a moved table with code or math in its cells no longer leaves a damaged
513
+ copy. Copied content no longer carries suggestion records.
514
+ - **A DOCX export never brings back a removed paragraph** (for example, a
515
+ rejected insertion) by returning the original file unchanged.
516
+ - **Highlight colors map by hue.** Office tints such as lavender no longer
517
+ show as gray, and mid or dark neutrals no longer show as green or yellow.
518
+ `style_blocks` can restore a block's original highlight.
519
+ - **PDF export draws SVG images** instead of blank space, and fetches an
520
+ image used on every page once.
521
+ - **HTML input with `<!-- comments -->`** no longer fails, and loose text
522
+ before a block keeps its place.
523
+ - **Turning page numbers off keeps an empty first-page footer**, so the
524
+ footer stays hidden on page 1.
525
+ - **Footnote edits.** Text in a just-inserted footnote is edited in place
526
+ instead of moving into the body. A find matches only visible footnote
527
+ text, not pending deletions. A batch that includes a footnote edit fails
528
+ or succeeds as a whole. `leave_comment` accepts a footnote that was read.
529
+ - **`replace` batches apply as planned.** Chained steps
530
+ (`Alpha→Beta`, `Beta→Gamma`), finds over a `search_result_id`, and
531
+ id-less `occurrence: "all"` finds are checked against each block's text
532
+ as earlier steps leave it. A step no longer lands on the wrong block or
533
+ sentence. Errors say when a long find drifts from the block, when the
534
+ block already contains the replacement, and that none of a failed call's
535
+ replacements applied.
536
+ - **`read_specific_blocks` reads a list item inside a table cell.**
537
+ - **NEL, LS, and PS characters read as spaces**, so a find copied from a
538
+ read matches.
27
539
 
28
- ## 3.1.6
540
+ ## 2.2.0
541
+
542
+ ### Added
543
+
544
+ - **ODT and RTF input.** `ReviseDocumentFormat` and `ReviseServerFormat` gain
545
+ `"odt"` and `"rtf"`, detected from `.odt` / `.rtf` filenames and from the
546
+ `application/vnd.oasis.opendocument.text`, `application/rtf`, and
547
+ `text/rtf` MIME types. Both import fonts, sizes, colors, highlighting,
548
+ character and paragraph formatting, headings, lists with their numbering,
549
+ tables with merged cells and column widths, images, hyperlinks, footnotes
550
+ and endnotes, headers and footers, comments, tracked changes, and page
551
+ size and margins. RTF from Word, WordPad, TextEdit, and LibreOffice is
552
+ supported, in any Windows code page or East Asian encoding. Each converter
553
+ loads only when a host first opens that format. `revise/server`'s
554
+ `parseDocument`, `fileToYDoc`, and `seedYDocFromFile` accept both. Host
555
+ code with an exhaustive `switch` over either type needs cases for the two
556
+ new values.
557
+ - **Delete whole table rows, columns, or tables from a cell selection.**
558
+ Backspace or Delete over fully selected rows or columns removes them, and
559
+ over every cell removes the table; a partial selection still clears only
560
+ the cell contents. Removing several rows is one undo step, and a table that
561
+ was the only block leaves an empty paragraph. Shift+click in another cell
562
+ of the same table now extends a cell selection, as dragging does.
563
+ - **Move connectors.** When a tracked move is focused, a line in the left
564
+ margin links where the text moved from to where it moved to, across pages.
565
+ It is not drawn in print preview.
566
+ - **Pleading-paper line numbers.** Documents whose page layout carries a
567
+ pleading grid show numbered rows (for example 1 to 28) at fixed positions
568
+ on every page, independent of the text, on screen and in PDF export. DOCX
569
+ export writes them as Word line numbers restarting on each page.
29
570
 
30
571
  ### Changed
31
572
 
32
- - **The agent skill knows when revise can't run.** In the Claude and ChatGPT
33
- apps, a document attached to the chat lives in a sandbox that can't install
34
- revise. The skill now stops before running anything there and offers the
35
- Revise app, which opens the document as an editable editor in the chat. If
36
- the app is connected, it uses it. Agents with a terminal are unaffected, and
37
- an install that fails on a network error is treated the same way instead of
38
- being worked around.
573
+ - **Margin line numbers behave like Word's.** Each number sits on its line's
574
+ baseline, table lines are not counted on screen (PDF already skipped
575
+ them), and a section that turns numbering off shows none instead of
576
+ inheriting the document setting. Numbers are set in the font that
577
+ dominates each page's text, on screen and in PDF, where they were always
578
+ Helvetica before.
579
+ - **The delegated agent can move blocks.** `agent.run()` and comment agents
580
+ can move paragraphs, lists, and tables as one tracked move (applied
581
+ directly in editing mode); blocks with anchored comments are not moved.
582
+ `move_blocks` is not part of the embedded tool list for `tools.*` hosts.
583
+ The delegated agent also recovers more reliably: it repairs a run that
584
+ edited and then reported no change, checks table fill work before it
585
+ finishes, and keeps the request and latest tool results when it recovers
586
+ from a context limit.
587
+ - **Suggestion cards show a date once a change is over a week old.** Old
588
+ changes read "Sep 4" or "Oct 11, 2013" instead of "4739d ago".
589
+ - **The footnote card is a compact row.** Clicking a footnote reference shows
590
+ its label with **Go to note** and **Remove**; the note is edited in the
591
+ note itself. In narrow layouts the card is centered under its reference
592
+ mark.
593
+
594
+ ### Fixed
595
+
596
+ - **Links.** Bare email addresses link and autolink as `mailto:`;
597
+ `mailto:` and `tel:` URLs are kept as typed; an `@` before the path is not
598
+ read as `https://` user info. Cmd+K uses the selected text as the link
599
+ target only when it is a full URL or an email address, and the link popup
600
+ finds a link Cmd+K just made on a backward selection.
601
+ - **Link, footnote, and inline-math popups line up at every zoom level.**
602
+ - **Math is no longer clipped when it renders before the KaTeX fonts load.**
603
+ Such results show provisionally and re-render once the fonts arrive, and
604
+ failed font or stylesheet fetches are not cached.
605
+ - **DOCX tracked moves of whole paragraphs, lists, and tables.** On import,
606
+ Word's paragraph-mark `w:moveFrom` / `w:moveTo` make the whole block part
607
+ of the move, so accepting it removes the source paragraph instead of
608
+ leaving an empty one, and a list split across a move becomes two lists.
609
+ Export writes paragraph marks and table rows with the move, and accepting
610
+ or rejecting resolves both halves together.
611
+ - **Accepting the deletion of every row of a table removes the table**, as
612
+ in Word, instead of leaving a table with no rows.
613
+ - **DOCX header and footer line breaks.** `w:br` in headers and footers is
614
+ imported, and export writes `w:br` instead of a raw newline that Word
615
+ showed as a space.
616
+ - **Header and footer layout.** In multi-column sections, headers and
617
+ footers span the full text width instead of one column; a zone is as wide
618
+ as its widest line; a bordered zone, such as a footer rule, spans the whole
619
+ band; and empty zones give up their space.
620
+ - **`replace_block` and `append_to_paragraph` on a non-text target**, such as
621
+ a table, fail with `target_type_mismatch` instead of doing nothing.
622
+ - **DOCX, ODT, and RTF open where `Blob.arrayBuffer` is missing** (Safari
623
+ before 14, jsdom). Files are read with a `FileReader` fallback.
624
+
625
+ ### Security
39
626
 
40
- ## 3.1.5
627
+ - **ODT and RTF import is hardened against hostile files.** Links pass a
628
+ scheme allowlist (http, https, mailto, tel, ftp, and relative), so
629
+ `javascript:` and similar are dropped. Self-referencing ODT deletions and
630
+ RTF control words such as `\constructor` can no longer overflow the stack
631
+ or swallow text, and imported tables are capped at 1,000 columns and
632
+ 100,000 cells.
41
633
 
42
- Agents finish document tasks in fewer commands. Measured on the revise
43
- benchmark, Claude Code and Codex finish its tasks for about 40% less with
44
- revise than without it.
634
+ ## 2.1.0
45
635
 
46
636
  ### Added
47
637
 
48
- - **`revise batch <file> '[...]'`** runs several tool calls (for example a
49
- table row and the total under it, or a `replace_all` and a `replace`) as one
50
- edit with one save. If any step fails, nothing is saved.
51
- - **`read --section 4,7,9`** reads several sections at once, `--blocks a..b`
52
- reads a range of ids, and `--count N` limits how many blocks are shown.
53
- - **`grep` takes several phrases** and shows about 80 characters around each
54
- match instead of the whole block (at most 40 blocks).
55
- - **`outline` lists headings typed as bold body text** first, each with the
56
- command that turns it into a real heading.
57
- - **PDF exports print the page count and paper size.**
638
+ - **`source` on document inputs.** `{ id, source: file }` names the field for
639
+ what it takes: DOCX, Markdown, plain text, or HTML. `docx` still works as the
640
+ same field; passing both with different values throws.
641
+ - **`context_notes` is optional in typed host calls.** `tools.execute()` and
642
+ `tools.call()` (browser and `revise/server`) fill in `"N/A"` for the read and
643
+ search tools, so application code no longer passes a model's working memory.
644
+ `executeDynamic()` keeps the schema requirement for model-provided calls.
645
+ - **`leave_comment` reports a retargeted anchor.** When the anchor text is not
646
+ in the named block and the comment goes to the only read block that has it,
647
+ `data.requestedBlockId` names the block you asked for and the message says so.
648
+
649
+ - **`read_table` and `edit_table_cells` agent tools.** Read a large table in
650
+ bounded windows (a summary, up to 50 rows, or one oversized cell in pages),
651
+ then set the plain text of up to 50 cells per call by row ID and column.
652
+ Cell text is written literally. Only cells a `read_table` call returned in
653
+ full can be edited, and that read stays valid across later `execute()` calls
654
+ on the same document while the cell and table geometry remain unchanged.
655
+ An invalid target rejects the whole batch with no changes. In suggesting mode each cell is its own suggestion. Read-only
656
+ surfaces and viewers get `read_table` only. Both tools are also in the
657
+ `revise/server` session. The SDK's `read_table` does not take the native
658
+ agent's task-declaration arguments (`task_kind`, `scope_*`,
659
+ `source_attachment_id`, `deliberate_blanks`). They are left out of the
660
+ published schema, and a call that supplies one fails with
661
+ `unsupported_argument` without reading anything. Empty placeholders
662
+ (`null`, `""`, `[]`) are ignored.
58
663
 
59
664
  ### Changed
60
665
 
61
- - **One `replace` call can edit several blocks:** leave out `id` and each
62
- `find` edits the one block you've read or grepped that contains it.
63
- - **Saves say what they rewrote:** "Rewrote N edited blocks; the rest of the
64
- file is copied byte for byte."
65
- - **`read` output is shorter:** it leaves out formatting that writing the
66
- block back restores anyway (a heading's own style, default table cell
67
- borders and padding, and the like).
68
- - **`outline` shows one id range per section** (`first..last`) and its word
69
- count.
70
- - **`compare` says what differs outside the redline:** header and footer
71
- text and page setup, or that the rest is formatting only.
72
- - **`--dry-run` with `--out`** previews instead of failing.
73
- - **The agent skill is a third shorter** and lists every field of `replace`
74
- and `leave_comment`, so agents don't need to look them up.
666
+ - **The delegated agent plans long tasks.** `agent.run()`, `revise_run_agent`,
667
+ and comment agents keep a step-by-step plan for multi-step work, update it
668
+ in the same turns as their edits, and save it with the conversation, so
669
+ fewer turns go to bookkeeping. The embedded tool list is unchanged: plan
670
+ tools stay inside the delegated agent.
671
+ - **Faster on long documents.** The scrollbar track and its markers are drawn
672
+ once and reused while scrolling, Find reuses each block's normalized text
673
+ between keystrokes, and tracked-change records are indexed in one pass
674
+ instead of one document walk per suggestion.
75
675
 
76
676
  ### Fixed
77
677
 
78
- - **`read --blocks a,b`** shows only those blocks, not every block between
79
- them.
80
- - **`outline` and `read --section`** see every section, not just the first 100.
81
- - **Rows added with `insert_table_row`** take the alignment, spacing,
82
- indents, and font of the row they're copied from.
678
+ - **DOCX paragraph spacing follows the document's rules.** `w:contextualSpacing` no longer
679
+ zeroes a paragraph's declared space before and after on import. Spacing is
680
+ resolved from neighboring paragraphs on screen, in table cells and
681
+ containers, and in PDF export: the gap between two paragraphs is the larger
682
+ of their spacings, not the sum, and contextual spacing drops it only between
683
+ paragraphs of the same style. PDF keep-with-next reserves the whole gap, and
684
+ exported DOCX keeps the declared spacing. Documents whose paragraphs both
685
+ declare spacing lay out tighter than in 2.0.x.
686
+ - **`style_blocks` with `list-style-type: none` turns list items into plain
687
+ paragraphs**, keeping their spacing and line spacing and applying the call's
688
+ other paragraph attributes in the same step.
689
+ - **Unsupported DOCX content can be suggested for removal.** In suggesting
690
+ mode, removing a block the editor preserves but cannot render (an opaque
691
+ DOCX payload) now becomes a tracked deletion.
692
+ - **Comment previews keep their layout.** In a comment chip's hover preview,
693
+ the avatar holds its size and a long author name is truncated.
694
+ - **An editor with no agent configured sends nothing.** `agent.run()`, the
695
+ `revise_run_agent` tool, and comment agents used to stream the document,
696
+ unauthenticated, to Revise's hosted agent and then report a generic
697
+ connection error. Without a `turnStream`, `baseUrl`, or `token`, they now
698
+ fail at once with `agent_not_configured` (`AgentNotConfiguredError` from
699
+ `agent.run()`), and `getToolDefinitions()` leaves the delegation tool out.
700
+ - **`documents.open()` activates the new document every time.** Opening a
701
+ document straight after another open, or after `documents.activate()`, left
702
+ the earlier one active. `documents.list()` status was also briefly stale
703
+ right after a document became ready.
704
+ - **`tools.getDefinitions()` lists only the native tools.** It included
705
+ `revise_run_agent`, which the docs say it leaves out.
706
+ - **Changing `agent.turnStream` no longer reloads the document.** A new
707
+ `turnStream` or `disableMetrics` value re-created the document runtime,
708
+ re-parsing the source and dropping unsaved edits, so an inline generator in
709
+ JSX reloaded the document on every render. Agent settings now apply to the
710
+ next run in place.
711
+ - **Reads are not refused for the life of the editor.** After a window had
712
+ been read once, every later `read_blocks_from_index` of it failed with
713
+ `no_new_read_context`, so a host agent's second conversation could not read
714
+ the document. The guard now resets with each call, like the other per-turn
715
+ limits.
716
+ - **Tool errors speak to SDK callers.** Messages no longer carry the internal
717
+ `Failed operation: <tool>: <Error>:` prefix or point at `<document_content>`,
718
+ which only Revise's own agent sees; they point at read results instead.
719
+ - **The open-error screen shows a plain message.** A corrupt file showed the
720
+ parser's internals (a zip library's message and link) to the person who
721
+ picked it. `onError` still receives the full detail. Loading text no longer
722
+ says "DOCX" for other formats, and a `File` source's title drops `.md`,
723
+ `.txt`, and `.html` extensions as well as `.docx`.
724
+ - **PDF export requests a failing font once.** When a font download failed
725
+ (a CSP or firewall blocking revise.io, say), export requested the same URL a
726
+ second time. The warning now says a fallback font was used and names
727
+ `setAssetBaseUrl()` for mirroring the fonts.
728
+ - **Readable errors from the package in Node.** Bundled code is wrapped at
729
+ short lines, so an uncaught error (such as the missing-`jsdom` hint) is no
730
+ longer printed under a 100 KB line of minified source.
731
+ - **Quieter host builds.** Vite no longer warns that `"buffer"` was
732
+ externalized, or prints the inlined WebAssembly's base64 as a file that
733
+ "doesn't exist at build time".
734
+
735
+ ## 2.0.1
83
736
 
84
- ## 3.1.4
737
+ ### Added
738
+
739
+ - **`tools.export({ format, mode })`.** Export as DOCX, PDF, HTML, Markdown,
740
+ or plain text from code, not just the ribbon's Export menu. `mode: "final"`
741
+ accepts every pending change and drops comments first for a clean copy;
742
+ the default `"review"` keeps tracked changes and comments in a .docx. The
743
+ editor-level `tools.export(options, documentId?)` routes to any open
744
+ document.
745
+ - **`exportDocument(source, options)` in `revise/server`.** The same export
746
+ for a room or a parsed document on the server: DOCX, HTML, Markdown, and
747
+ plain text, in review or final mode.
748
+ - **`onImageUpload(file, documentId)`.** Store images users insert, paste, or
749
+ drop in your own storage and return the URL the document should use.
85
750
 
86
751
  ### Fixed
87
752
 
88
- - **The package README's heading** reads `revise`.
753
+ - **Inserting, pasting, or dropping an image works.** It used to post to
754
+ Revise's app API, which the SDK cannot reach, so the image never appeared.
755
+ Without `onImageUpload`, images are now embedded in the document as data
756
+ URLs and export into the .docx. `toolbar.insertImage()` resolves `false`
757
+ when an upload fails, and the failure reaches `onError`.
758
+ - **Docs:** linked moves are described correctly in Support, the reserved
759
+ collaboration keys point to `RESERVED_DOCUMENT_KEYS`, and the delegated
760
+ agent page says how to get hosted-agent access.
89
761
 
90
- ## 3.1.3
762
+ ## 2.0.0
763
+
764
+ The SDK is now public: `npm i revise`. No account, token, or contact
765
+ with us is needed to install it. 2.0.0 also ships everything from the
766
+ 2.0.0-alpha releases below.
91
767
 
92
768
  ### Changed
93
769
 
94
- - **The package README** has a plain heading and tagline. No changes to the
95
- CLI or the library.
770
+ - **BREAKING: the package is now `revise`.** The private `@reviseio/sdk`
771
+ package is retired. Update the dependency and imports:
772
+ `@reviseio/sdk` → `revise/editor`, `@reviseio/sdk/full` →
773
+ `revise/editor/full`, `@reviseio/sdk/backend` → `revise/server`, and
774
+ `@reviseio/sdk/style.css` → `revise/style.css`. Remove the `@reviseio`
775
+ scope and token lines from `.npmrc`.
776
+ - **New license: free for evaluation, personal projects, and education.**
777
+ Production use by businesses, nonprofits, and government requires a paid
778
+ license. See `LICENSE` and [the license page](https://revise.io/developer/docs/editor-sdk/license).
779
+ The previous 60-day evaluation terms no longer apply.
780
+ - **The editor fills its container at any size.** The 640×560px minimum is
781
+ gone, so the editor fits phone-width columns and short panels without
782
+ overflowing them. A container with no height gets a 560px fallback and a
783
+ one-time console warning instead of a collapsed editor.
784
+ - **Hosted agent defaults to production.** Without `agent.baseUrl`, the
785
+ delegated Revise agent now targets `https://agent.revise.io` instead of a
786
+ development address.
96
787
 
97
- ## 3.1.2
788
+ ### Added
789
+
790
+ - **A 4.5 MB package, with assets loaded on demand.** PDF export fonts were
791
+ inlined as base64 and made up three quarters of the package; they, the math
792
+ fonts and stylesheet, the pdf.js worker, and Tree-sitter grammars now load
793
+ from `https://revise.io` when first needed. **`setAssetBaseUrl(url)`**
794
+ points the SDK at a self-hosted mirror.
795
+ - **`import ReviseEditor from "revise/editor"`.** The editor entry now has a
796
+ default export. The named `ReviseEditor` export still works.
797
+ - **`revise` root entry** with `REVISE_SDK_VERSION`, `REVISE_SDK_BUILD`, and
798
+ the shared types, and no runtime weight.
799
+ - **`THIRD-PARTY-NOTICES.md`** lists every bundled open-source package with
800
+ its license.
801
+ - **Anonymous usage ping, and the `telemetry` prop to turn it off.** Once
802
+ per page load, the editor sends Revise its version; the browser adds the
803
+ site's origin. Development hosts are counted per day and version without
804
+ their origin. No cookies, user data, or document content.
805
+ `telemetry={false}` disables it.
806
+
807
+ ### Fixed
808
+
809
+ - **Math renders with its real fonts in host apps.** Equations looked for
810
+ their fonts and stylesheet at the host's own `/fonts` and `/katex.min.css`
811
+ and fell back to system fonts; the help link in the editor menu also
812
+ pointed at the host's `/help`. All now resolve to Revise's assets.
813
+ - **The SDK no longer reaches for development servers.** Revise application
814
+ endpoints (document history, preferences, uploads, failure reports) and the
815
+ sync-server addresses no longer resolve to `localhost` in an embedding
816
+ host. Document history in particular fetched from `localhost:3001` in
817
+ browsers without a `process` global.
818
+ - **No debug globals on the host's `window`.** `__getEditor`,
819
+ `__getDocLayout`, and `__aiLogs` are no longer installed.
820
+ - **DOCX math export uses Revise's own MathML → OMML converter.** Equations
821
+ export to native Word math (fractions, radicals, scripts, sums and
822
+ integrals with limits, delimiters, matrices, accents, bars, braces,
823
+ functions, boxed and text runs) with no third-party copyleft code in the
824
+ package. Re-importing them is more faithful: `\left\{ … \right.`,
825
+ `\underline`, `\overbrace`, `\boxed`, `\text{…}`, `\mathbb`, binomials,
826
+ and named functions (`\sin`, `\log`, `\lim_{…}`) now come back as the
827
+ same LaTeX instead of approximations, and symbols no longer run into the
828
+ following letter (`\alpha x`, not `\alphax`).
829
+
830
+ ## 2.0.0-alpha.7
831
+
832
+ ### Fixed
833
+
834
+ - **DOCX round trips keep every modeled mark and block.** A new
835
+ export → import matrix (every formatting mark in every text context,
836
+ every paragraph, list, table, cell, image, code, math, note, header,
837
+ footer, and page-layout attribute, plus a second-pass fixed-point
838
+ check) found and pinned a set of losses: lists inside table cells
839
+ were dropped on export; hanging indents exported as zero and
840
+ `w:hanging` was ignored on import; headings came back as Word's blue
841
+ 16pt built-ins (export now writes the editor's heading sizes with
842
+ inherited color); unscoped header/footer blocks were not exported;
843
+ hyperlinks discarded an explicit text color; links inside footnotes
844
+ were lost on import; header and footer runs used a reduced codec in
845
+ both directions and now share the body run codec, links and inline
846
+ code included; inline code and code blocks flattened to Courier text
847
+ and now travel as `CodeInline` / `CodeBlock_<language>` styles and
848
+ return as the original nodes; todo items exported as literal
849
+ `[x]` text and now use checkbox glyphs that re-import as todo lists
850
+ with their checked state; code-block line breaks doubled on
851
+ re-import; and a single run in another font restamped the whole
852
+ document (the inferred document font is now the character-weighted
853
+ majority).
854
+ - **Table borders export and re-import faithfully.** Export no longer
855
+ throws on non-hex colors such as `TRANSPARENT`, `rgba()`, or CSS
856
+ names — unresolvable values are omitted or written as `auto`. The
857
+ uniform `borderWidth`/`borderColor` pair is honored (width 0 means
858
+ no borders), width-0 spec edges export as `none` instead of a
859
+ hairline, and an explicit `w:sz="0"` imports as hidden rather than a
860
+ 1px line. Table Settings border changes now rewrite the structured
861
+ table spec and clear per-cell overrides, so hiding borders on an
862
+ imported table takes effect.
863
+ - **Byte-preserving DOCX export degrades instead of failing.** A carrier
864
+ that fails to load falls back to the regenerated package like every
865
+ other graft failure; the graft option reports its outcome (exact,
866
+ grafted, regenerated, and the fallback code) through an isolated
867
+ callback that can never break an export. Untouched imports of rich
868
+ documents now export byte-identical: note-body font inheritance,
869
+ header/footer zone ids, and legacy chrome no longer drift the
870
+ fidelity signatures; watermark and settings edits graft instead of
871
+ restoring carrier values; body grafting is invalidated when wrapper
872
+ or style sidecars change; single-quoted and non-numeric relationship
873
+ ids parse; and a changed header image is replaced even when its
874
+ media filename collides.
875
+ - **Formatting suggestions preserve footnotes.** Accepting a
876
+ `style_blocks` suggestion keeps footnote references and bodies.
877
+ - **Large documents no longer stall on batch edits.** Styling 205 blocks
878
+ in a 10,000-block document, applying 100 replacements, and large
879
+ multi-block insertions run without re-decoding the document per
880
+ action; suggestion projection latency is bounded; batch paragraph
881
+ formatting suggestions behave identically through preview,
882
+ acceptance, and rejection.
883
+ - **Semantic tool errors and inputs.** Errors distinguish Markdown find
884
+ syntax from stored plain text; metric CSS paragraph indentation
885
+ (`cm`, `mm`) is accepted; number-dot prose can be parsed as inline
886
+ text instead of a list when requested.
887
+ - **Comments render AI citations.** Structured citations persist on
888
+ replies and render in the panel; unsupported provider citation
889
+ markers are hidden, including on legacy comments.
890
+ - **Agent image rehosting.** Wikimedia thumbnail URLs are recovered by
891
+ rehosting the original image, and rate-limited rehosts surface the
892
+ backend reason and status.
893
+ - **Revision timeline never collapses to zero.** A stale or missing
894
+ server update counter no longer disables history or pins every frame
895
+ to the first update; loaded frames are authoritative.
896
+ - **Pasted images write once.** A pasted image no longer inserts a
897
+ temporary base64 placeholder that is replaced later; the final hosted
898
+ URL is written at the captured paste position when the upload
899
+ completes.
98
900
 
99
901
  ### Changed
100
902
 
101
- - **`revise skill install` installs where the agent running it reads
102
- skills:** `.claude/skills` from Claude Code or in a project with a
103
- `.claude` folder, otherwise `.agents/skills`, which Codex, Cursor, Copilot,
104
- and others read. It used to fall back to `.claude/skills`, which other
105
- agents don't read.
106
- - **It ends by saying to read the installed SKILL.md now:** a running agent
107
- session doesn't load a newly installed skill; new sessions do. The
108
- quickest install for any agent with a terminal is
109
- `npx -y revise@latest skill install`.
903
+ - **Comment margin geometry is direction-aware.** Chip, floating-stack,
904
+ and insert-chip positions are computed along an outward axis with a
905
+ single conversion to physical coordinates. The embedded document
906
+ surface itself is still laid out left-to-right: the margin chrome
907
+ stays on the page's right regardless of the host page's direction.
908
+ Mirroring the embed for right-to-left hosts is not part of this
909
+ release.
910
+
911
+ ## 2.0.0-alpha.6
912
+
913
+ ### Fixed
914
+
915
+ - **A healed seed race now recovers full fidelity — and never loses a
916
+ comment.** Three repair refinements: the winner is the seed whose
917
+ metadata survived the merge (each seed stamps a ballot in the same
918
+ transaction), so the kept content matches the surviving import
919
+ capture; a shared deterministic id keeps the WINNER's element, not an
920
+ arbitrary one; and map records under a shared key (deterministic
921
+ comment ids) are never deleted — the merge already deduplicated them,
922
+ and alpha.5's repair removed the only surviving record. A raced,
923
+ repaired room now reports "exact" and exports byte-identically.
924
+
925
+ ## 2.0.0-alpha.5
926
+
927
+ ### Fixed
928
+
929
+ - **Seed-race repair kept a duplicate footnote.** Deterministic ids that
930
+ every seed generates identically (docx footnotes) were protected from
931
+ repair as a collision safeguard, leaving one copy per seed. Repair now
932
+ keeps exactly one occurrence of a shared id. Supersedes 2.0.0-alpha.4,
933
+ which was deprecated minutes after publish.
934
+
935
+ ## 2.0.0-alpha.4
936
+
937
+ ### Fixed
938
+
939
+ - **Double-seed connect race no longer duplicates the document.** Two
940
+ peers that each found an empty room and seeded the same file before
941
+ syncing used to merge into a perfectly-synced, perfectly-duplicated
942
+ document. Every seed now records a claim in the same transaction as
943
+ its content, and any peer that sees two claims deterministically
944
+ removes the losing seed's content — idempotent, convergent, and
945
+ content added after a seed is never touched. `seedYDocFromFile` is
946
+ now genuinely safe to call on every connection: a later call also
947
+ heals an already-raced room, and every live editor session repairs
948
+ one the moment the second claim syncs in.
949
+ - **Editing no longer rewrites document properties.** A structural edit
950
+ (or a rejected tracked change) permanently dropped the imported core
951
+ properties from the live model, so every later export regenerated
952
+ `docProps/core.xml` with an "Un-named" creator, the title removed,
953
+ and the creation date reset to export time. Core properties now
954
+ survive every model rebuild, and when core.xml IS legitimately
955
+ regenerated it is a faithful merge: `cp:revision` round-trips and
956
+ fields the original never had are not invented.
957
+ - **`docProps/app.xml` passes through untouched.** It is never
958
+ regenerated (preserving Application/Company/TotalTime) and never
959
+ added to a package that did not have one.
960
+
961
+ ### Added
110
962
 
111
- ## 3.1.1
963
+ - **`repairSeedRace(ydoc)`** on the backend entry (with
964
+ `SeedRaceRepairResult`): detect and repair a double-seed race on
965
+ demand. Editor sessions and `seedYDocFromFile` run it for you.
112
966
 
113
967
  ### Changed
114
968
 
115
- - **The agent skill is `revise-cli`.** `revise skill install` writes
116
- `.agents/skills/revise-cli/` (or `.claude/skills/revise-cli/`) and replaces
117
- the `revise/` folder earlier versions installed. As plugins it's
118
- `cli@revise`: `claude plugin install cli@revise`,
119
- `codex plugin add cli@revise`, or
120
- `npx skills add reviseio/skills --skill revise-cli`.
969
+ - **New reserved top-level key in shared documents: `"seed-claims"`**
970
+ (see `RESERVED_DOCUMENT_KEYS`) — where seed claims live.
121
971
 
122
- ## 3.1.0
972
+ ## 2.0.0-alpha.3
973
+
974
+ ### Fixed
975
+
976
+ - **Backspace before a chip deleted the chip.** A preserved-object chip
977
+ has two caret stops — before and after — and a delete now respects
978
+ which side the caret is on, like a caret between two characters:
979
+ backspace at the before-stop targets the block BEFORE the chip (an
980
+ atomic neighbor is deleted whole, a text neighbor loses its last
981
+ character), and forward delete at the after-stop targets the block
982
+ after. Deletes pointing AT the chip still remove it.
983
+ - **Up/down arrows at a chip slid the caret to the chip's other side**
984
+ instead of changing lines. Vertical movement now leaves the chip's
985
+ line and lands on the neighboring block's stop nearest the caret's
986
+ column — arrowing through a stack of chips keeps the caret on the
987
+ same side all the way down.
988
+
989
+ ## 2.0.0-alpha.2
990
+
991
+ ### Fixed
992
+
993
+ - **Exporting .docx could crash in production builds of the host app**
994
+ ("Cannot destructure property 'default' … as it is undefined" from
995
+ the converter's zip loader). The SDK's build emitted duplicate
996
+ interop chunks for its zip dependency behind dynamic imports, and
997
+ some consumer bundlers resolved one family to `undefined` when
998
+ producing production builds — development builds were unaffected,
999
+ which is why the crash only appeared after deployment. The dependency
1000
+ is now a static import inside the (still lazily loaded) converter
1001
+ modules: the load profile is unchanged and the chunk graph no longer
1002
+ depends on the host bundler's interop handling.
1003
+ - **Backspace in an empty paragraph directly after a chip deleted the
1004
+ chip** instead of the paragraph. Preserved payloads are content the
1005
+ source file owns, not editor furniture: the empty paragraph dies, the
1006
+ chip survives. (Page and section breaks keep their old
1007
+ consume-on-backspace behavior.)
1008
+ - **Chips gained real before/after caret stops.** The caret can now be
1009
+ placed on either side of a chip — arrow keys walk across it, and
1010
+ clicking the left or right half of the chip places the caret on the
1011
+ matching side.
1012
+
1013
+ ## 2.0.0-alpha.1
1014
+
1015
+ Prerelease for evaluation. The 2.0 line's headline is DOCX source
1016
+ fidelity: a document imported from .docx can now leave the editor as the
1017
+ file it came from, not a reconstruction of it.
123
1018
 
124
1019
  ### Added
125
1020
 
126
- - **`--blocks` on `changes`, `accept`, and `reject`.** Select tracked
127
- changes by block: ids (`--blocks a1B2c3,d4E5f6`) or a range in document
128
- order (`--blocks a1B2c3..d4E5f6`). Ids of list items, table cells, and
129
- paragraphs inside them work. In the library: `{ blocks: [...] }`, with
130
- ranges as `{ from, to }`.
131
- - **`--view tracked|accepted|original`** on `read`, `grep`, `search`,
132
- `export`, and `convert`. `read` now shows pending changes inline as
133
- `<del>` and `<ins>` with their change ids and authors; `grep` and `search`
134
- find text on both sides of a change and say which side it's on. `export`
135
- and `convert` with `--view original` write the document as it was before
136
- every pending change. `--final` still means `--view accepted`.
137
- - **`replace-all --ignore-case` and `--exact`.**
1021
+ - **DOCX source-fidelity mode (default on).** Importing a .docx keeps the
1022
+ original package inside the document (the "carrier", shared documents
1023
+ included, capped at 25MB). On export, content you did not touch is
1024
+ emitted as the exact bytes that arrived — byte-for-byte, unannotated —
1025
+ and only changed content is regenerated. A verification stage inspects
1026
+ every composed package and falls back to full regeneration rather than
1027
+ ship anything it cannot verify.
1028
+ - **`handle.getSourceFidelity()`** (and `ydocSourceFidelity(ydoc)` /
1029
+ `documentToDocx(doc, { originalDocx })` on the backend entry) reports
1030
+ the honest relationship of the next export to the original file:
1031
+ `"exact"` (byte-identical), `"grafted"` (original bytes plus your
1032
+ edits), or `"converted"` (no usable original; the report says why).
1033
+ - **Unmodeled Word formatting survives editing.** Run, paragraph, table,
1034
+ row, cell, and section properties the editor does not model (vendor
1035
+ effects such as `w14:glow`, revision-save ids, row heights, table
1036
+ look flags, page borders, note-numbering properties…) are carried
1037
+ through the model and re-emitted — so an EDITED paragraph keeps them
1038
+ too, with or without the carrier.
1039
+ - **Preserved objects render as labeled chips.** OLE embeds (Excel,
1040
+ Visio), SmartArt without a raster fallback, and unknown OOXML
1041
+ constructs import as atomic blocks labeled with their source tag
1042
+ (e.g. "w:object · Excel.Sheet.12"), render as chips on canvas and in
1043
+ PDF export, and re-export verbatim. In agent HTML they appear as
1044
+ `<docx-raw id tag/>`: an agent can keep, move, or omit one
1045
+ (omission deletes), but can never inject raw OOXML of its own.
1046
+ - **Editable-region permissions preserved.** `w:permStart`/`w:permEnd`
1047
+ pairs (and future paired ranges) survive import, editing, and export
1048
+ with balance guaranteed by construction: typing inside extends the
1049
+ region, deleting its text retires it, and unbalanced pairs in source
1050
+ files are repaired at import.
138
1051
 
139
1052
  ### Changed
140
1053
 
141
- - **`replace-text` is now `replace-all`** (`replaceAll` in the library). It
142
- replaces in page headers and footers and in footnotes and endnotes as well
143
- as the body, and says where. Curly and straight quotes, no-break and plain
144
- spaces, and no-break and plain hyphens match each other unless `--exact`,
145
- and the replacement keeps the document's characters: `"net 30"` →
146
- `"net 45"` keeps its no-break space. Matches it leaves alone, like other
147
- capitalization, are reported as `nearMisses`. `replace-text` and
148
- `replaceText` still work, and JSON output run under `replace-text` still
149
- names it.
150
- - **`--section` is a heading and everything under it.** `--section 8`
151
- includes 8.1 and 8.2. Numbers match whether typed or Word's automatic
152
- numbering. A title matches in full, or by text in only one heading; text in
153
- several headings is an error (`section_ambiguous`), and a section that
154
- doesn't exist is `section_not_found` instead of an empty result.
155
- - **Clearer flag names:** `new --content` (was `--from`), `new --page-size`
156
- (was `--page`), `search --results-page` (was `--page`), and `--blocks` for
157
- block ids on `read` and `replace-all` (was `--ids`). The old names still
158
- work.
159
- - **`changes` lists header, footer, and note changes as such** ("Header",
160
- "Footnote 1"), with their text.
161
-
162
- ### Fixed
163
-
164
- - **Word-numbered headings.** Headings numbered by Word's heading styles, how
165
- most contracts number clauses, are headings again: `outline` lists them
166
- with their numbers ("8.1 Cap on liability") and `--section 8` finds them.
167
- - **Comparing numbered documents.** Two copies of the same numbered document
168
- compare as unchanged, instead of every numbered clause deleted and
169
- reinserted.
170
- - **Comparing against a file revise edited.** A one-word edit compares as a
171
- one-word change, not a whole paragraph replaced: editing a paragraph no
172
- longer adds fonts and sizes to it or its neighbors.
173
- - **Tracked changes in headers and footers** are saved as Word revisions, and
174
- ones made in Word open as pending changes.
175
- - **Markdown export** numbers nested list items per level (8.1 was written
176
- as "9."), and writes numbered headings as headings: `## 8.1 Cap on
177
- liability`.
178
-
179
- ## 3.0.1
180
-
181
- ### Fixed
182
-
183
- - **Windows-1252 text on Node 20.** Text that isn't UTF-8, like a .txt file
184
- from a Windows editor piped to `convert`, and RTF files read € “ ” ‘ ’ – —
185
- and the other characters Windows-1252 stores in bytes 0x80–0x9F as
186
- invisible control characters. Node 22 and later were not affected.
187
-
188
- ## 3.0.0
189
-
190
- The first release of `revise` as a command-line tool and TypeScript library
191
- for reading, editing, and redlining Word documents.
192
-
193
- Versions 2.x of this package were the Revise editor for React. The editor is
194
- now [`@reviseio/editor`](https://www.npmjs.com/package/@reviseio/editor); 2.x
195
- stays installable.
196
-
197
- ### Added
198
-
199
- - **The `revise` CLI.** Read a document as HTML with block ids, search it,
200
- edit it with the same tools the Revise agent uses, and save the file in
201
- place, as tracked changes by default in .docx. Review with `changes`,
202
- `diff`, `accept`, and `reject`; `undo` and `restore` work across edits;
203
- `render` draws pages as images; `export`, `convert`, `compare`, and `new`
204
- write .docx, PDF, Markdown, HTML, and text. `convert` also works in a
205
- pipe: `-` reads stdin (the format is recognized from its bytes) or writes
206
- stdout. `--out new.docx` on an edit saves the result as a new file and
207
- leaves the original as it is. Every command has its own
208
- `--help`, and colored output on a terminal (not in pipes unless
209
- `FORCE_COLOR` is set; never with `--json`).
210
- - **`--json` on every command**: one envelope (`schema`, `ok`, `command`,
211
- `meta`, `data`, `warnings`, `error`) with stable error codes, structured
212
- partial results, and exit codes that say whether anything was saved.
213
- Specified in [JSON output](https://revise.io/developer/docs/revise/json) and shipped as a JSON Schema,
214
- `revise/cli-output.schema.json`.
215
- - **`ReviseDocument`**, the same operations as a library: open a file or
216
- bytes, run typed tools, review changes, export with a fidelity report,
217
- and snapshot and restore state.
218
- - **`agentTools(doc, { provider })`**: the editing tools in the shapes the
219
- Anthropic and OpenAI SDKs expect, with a matching result formatter.
220
- - **Collaboration rooms.** `seedYDoc(room, file)` seeds a sync server's
221
- Y.Doc on every connection (idempotent, repairs two peers that seeded at
222
- once, keeps the original Word file in the room), and
223
- `ReviseDocument.fromYDoc(room)` edits and exports a live room.
224
- - **Word fidelity.** Untouched content in a .docx exports byte for byte;
225
- `xml` commands read and patch the raw package for what the tools don't
226
- cover (styles, numbering, settings).
227
- - **An agent skill**: `revise skill install` writes a SKILL.md that teaches
228
- coding agents the CLI.
1054
+ - **BREAKING: two new reserved top-level keys in shared documents** —
1055
+ `"docx-carrier"` and `"oxml-ranges"` (see
1056
+ `RESERVED_DOCUMENT_KEYS`). A host-built Y.Doc already using these
1057
+ names is rejected by `assertUsableSharedDocument`.
1058
+ - **BREAKING: docx-sourced exports are byte-preserving by default.**
1059
+ 1.x regenerated every export from the model; 2.0 reproduces original
1060
+ bytes for untouched content. Hosts that depended on exports being
1061
+ normalized into the generated dialect should convert explicitly.
1062
+ - `ReviseDocument` block children may now include the `"docx-raw"`
1063
+ node type (opaque; convert rather than inspect, as ever).
1064
+ - Shared documents built from a .docx are larger by roughly the size of
1065
+ the source file (the carrier). It is stored once, chunked, and synced
1066
+ like any other document state.
229
1067
 
230
- ### Removed
1068
+ ## 1.3.1
1069
+
1070
+ ### Fixed
1071
+
1072
+ - **Delegated page inspection now reaches the embedded editor canvas.** The
1073
+ SDK connects the delegated agent's `render_document_pages` tool to the
1074
+ mounted document renderer, so appearance and layout requests return the
1075
+ actual pages instead of reporting that canvas inspection is unavailable.
1076
+ - **Agent-tool documentation now matches the generated SDK catalog.** The
1077
+ public docs use the canonical `remove_blocks` name, distinguish the
1078
+ deterministic document-local tool subset from delegated-agent-only tools,
1079
+ and explain where visual page inspection is available.
1080
+
1081
+ ## 1.3.0
1082
+
1083
+ ### Added
1084
+
1085
+ - **The built-in editor UI now localizes itself in English, Spanish, and
1086
+ German.** Ribbon controls, menus, dialogs, comments, Review mode, and agent
1087
+ chrome follow the browser language or the persisted Revise UI-language
1088
+ preference, while English remains the fallback if a locale chunk cannot be
1089
+ loaded.
1090
+ - **The delegated browser agent can inspect the document's rendered pages.**
1091
+ It can request bounded appearance contact sheets or layout diagnostics from
1092
+ the real canvas renderer, including page geometry, tables, images, math,
1093
+ headers, footers, and safe placeholders for unavailable visual assets.
1094
+
1095
+ ### Changed
1096
+
1097
+ - **Tab editing and layout now follow Word-style paragraph behavior.** Tab and
1098
+ Shift+Tab at the start of a block keep indenting or outdenting, while either
1099
+ key inside paragraph text inserts a tab. Long tabbed lines wrap at word
1100
+ boundaries, restart their ruler on each visual line, and preserve custom,
1101
+ aligned, leader, and right-to-left tab stops.
1102
+
1103
+ ### Fixed
1104
+
1105
+ - **DOCX named styles remain stable through editing and repeated round trips.**
1106
+ Imported paragraph styles and document defaults now drive newly created
1107
+ headings and agent-created styled blocks, survive Yjs persistence, suppress
1108
+ redundant direct formatting on export, and converge without accumulating
1109
+ unused generated Word styles. Explicit formatting resets, borders, spacing,
1110
+ fonts, and styles inside table cells remain intact.
1111
+ - **Agent document measurements reconcile pending Review changes.** Primary
1112
+ totals consistently measure the final, as-if-accepted document and include
1113
+ the original review projection when pending suggestions make the visible
1114
+ word or character count differ.
1115
+
1116
+ ## 1.2.0
1117
+
1118
+ ### Added
1119
+
1120
+ - **International text support now extends across the editing and conversion
1121
+ pipeline.** Unicode-aware line breaking, search, list numbering, font
1122
+ fallback, and IME composition preserve multilingual text more reliably, and
1123
+ text import now detects UTF-8 and UTF-16 files. HTML, DOCX, RTF, ODT, and
1124
+ plain-text conversions keep the expanded script coverage intact.
1125
+ - **Orange and purple join the SDK highlight palette.** The editor UI,
1126
+ `find_highlights`, `style_blocks`, agent HTML, and DOCX round trips now
1127
+ share the same seven canonical highlight colors.
1128
+ - **Agent styling covers richer document structures.** `style_blocks` adds
1129
+ span, descendant-wildcard, first-row, and named-paragraph-style selectors,
1130
+ with durable mappings for image sizing and alignment, paragraph borders,
1131
+ nested tables and lists, per-edge cell borders, cell fills, padding, and
1132
+ table-cell text styles.
1133
+
1134
+ ### Fixed
1135
+
1136
+ - **DOCX import follows Word's effective paragraph and table styling.**
1137
+ Unstyled paragraphs inherit the document's default style; exact and
1138
+ at-least line rules use the resolved font size; paragraph before/after and
1139
+ contextual spacing replace the editor's fallback gap; missing table borders
1140
+ remain borderless; and non-uniform cell margins survive import. The imported
1141
+ spacing persists through Yjs, paragraph splits and merges, HTML, DOCX, and
1142
+ PDF output, keeping compact Word layouts from growing onto extra pages.
1143
+ - **Unavailable Word fonts use the document's own substitution hints.** DOCX
1144
+ import reads `fontTable.xml` alternate names and PANOSE/family/pitch
1145
+ metadata, persists them with the document, and chooses metric-compatible
1146
+ fallbacks before resorting to a generic family.
1147
+ - **Multilingual PDF export embeds and shapes the scripts it needs.** Chinese,
1148
+ Japanese, Korean, Indic, Southeast Asian, Tibetan, Ethiopic, Armenian,
1149
+ Georgian, Syriac, Thaana, symbols, emoji, and rare Han use bundled lazy
1150
+ fallback faces, while a hidden logical-text layer preserves search and text
1151
+ extraction.
1152
+ - **Agent edits preserve complex formatting and pending review state.** Styled
1153
+ tables, nested content, list-item formatting, explicit text overrides,
1154
+ comments, and edits layered over pending insertions now survive preview,
1155
+ acceptance, and rejection without duplicating or flattening structure.
1156
+ - **Borderless layout tables stay visually borderless while editing.** The
1157
+ canvas now reveals only the specific invisible vertical edge under a resize
1158
+ pointer instead of ghosting the table's entire grid on hover or focus.
1159
+ - **Imported pale-yellow highlights remain highlights.** HTML clipboard import
1160
+ no longer remaps Word's pale yellow to the editor's green palette entry.
1161
+
1162
+ ## 1.1.0
1163
+
1164
+ ### Added
1165
+
1166
+ - **First-class right-to-left editing.** The built-in toolbar can set paragraph
1167
+ and list direction to automatic, LTR, or RTL. Mixed Hebrew, Arabic, and
1168
+ left-to-right text now uses bidi-aware line layout, visual arrow-key
1169
+ movement, stable caret and selection geometry, direction-aware alignment and
1170
+ indents, mirrored list markers, and RTL tab stops. Direction survives Yjs,
1171
+ clipboard and agent edits, HTML, and DOCX round trips; PDF export preserves
1172
+ mixed-direction reading order and positioning.
1173
+ - **Multi-column sections.** Page layout now supports one, two, or three
1174
+ newspaper-style columns with a configurable gap. Continuous section breaks
1175
+ balance their final columns, while page and next-page sections keep ordinary
1176
+ pagination. The canvas editor and PDF export share the flow rules, DOCX and
1177
+ HTML import/export preserve the settings, and `set_page_layout` exposes
1178
+ `columnCount`, `columnGap`, and section-scoped updates to browser and
1179
+ server agent sessions.
1180
+ - **Native document-structure tools.** `insert_block` can create a live table
1181
+ of contents with `<toc levels="3"></toc>`. The canonical
1182
+ `remove_blocks` tool can delete a counted range, exact IDs, a saved search
1183
+ result, or an explicitly authorized document tail with `through_end`.
1184
+
1185
+ ### Changed
1186
+
1187
+ - **Agent tool sessions avoid unproductive read cycles.** Sequential reads now
1188
+ reject windows containing only blocks already returned in the same request
1189
+ with `no_new_read_context`; `read_specific_blocks` remains available for
1190
+ intentional revisits. `remove_blocks` is now the model-facing name, while
1191
+ the previous `remove_block` name remains an executable compatibility alias.
1192
+
1193
+ ### Fixed
1194
+
1195
+ - **Strict-provider nulls behave like omitted optional tool fields.** Browser
1196
+ and server tool execution normalize provider-materialized `null` values
1197
+ from the generated schema before dispatch, without stripping required or
1198
+ deliberately nullable values. Optional layout and mutation inputs therefore
1199
+ no longer take invalid branches merely because a provider filled them in.
1200
+ - **Agent-generated Unicode escapes become the intended text.** Literal
1201
+ `\uXXXX` sequences in agent HTML and replacement paths are decoded without
1202
+ disturbing escaped backslashes or code spans, preventing visible escape text
1203
+ in edited documents.
1204
+ - **Review decisions preserve the reader's place.** Accepting or rejecting a
1205
+ tracked change no longer forces the embedded editor to scroll back to the
1206
+ active suggestion.
1207
+ - **SDK PDF export keeps Hebrew and Arabic text self-contained.** The package
1208
+ now bundles the Noto fallback faces used by RTL export, so embedding hosts do
1209
+ not need to mirror Revise's public font directory to avoid dropped glyphs.
1210
+
1211
+ ## 1.0.1
1212
+
1213
+ ### Fixed
1214
+
1215
+ - **Malformed model input can no longer crash a host's agent loop.** A bare
1216
+ string where `search_document` expects a `queries` array — the most
1217
+ common model slip — threw a raw `TypeError` out of `execute()` /
1218
+ `executeDynamic()` instead of returning a structured failure. Bare
1219
+ strings are now coerced to one-element arrays (also for
1220
+ `read_specific_blocks`' `block_ids`), anything uncoercible fails
1221
+ structurally, and both surfaces gained a safety net that converts an
1222
+ unexpected handler throw into an `internal_error` result. The documented
1223
+ contract — expected failures as results, only environment errors reject —
1224
+ now holds for arbitrary input.
1225
+ - **Invalid enum values no longer mutate the wrong target silently.** An
1226
+ insert tool called with `position: "above"` placed content _after_ the
1227
+ reference block while reporting success, and `set_header_footer` with a
1228
+ misspelled or missing `side` edited the header. Both now return a
1229
+ structured failure naming the valid values.
1230
+
1231
+ ## 1.0.0
1232
+
1233
+ One package, one tool contract. The browser and server surfaces now speak
1234
+ the same canonical envelope, so host result-handling code is shared verbatim
1235
+ between web and Node. That convergence is breaking on the browser side —
1236
+ every change is listed below.
1237
+
1238
+ ### Breaking
1239
+
1240
+ - **`tools.execute()` returns the canonical discriminated envelope.** The
1241
+ flat `{ toolCallId, name, success, error?, agentFeedback?, output?,
1242
+ documentContent? }` result is gone. Both surfaces now return
1243
+ `{ ok: true, value: { callId, tool, message, data, context, suggestionIds } }`
1244
+ or `{ ok: false, error: { callId, tool, code, message } }`
1245
+ (`ReviseToolResult`). Field mapping: `toolCallId → value.callId`,
1246
+ `name → value.tool`, `agentFeedback → value.message`,
1247
+ `output → value.data`, `documentContent → value.context.html`;
1248
+ `view_image`'s attachment lives on `value.image`.
1249
+ `ReviseEditorToolExecutionResult` no longer exists.
1250
+ - **`tools.execute()` is typed and no longer routes `document_id`.**
1251
+ `execute()`/`call()` take the generated per-tool input types and
1252
+ cover the shared 24-tool contract; untrusted model calls — including the
1253
+ browser-only `get_selection`, `view_image`, and
1254
+ `revise_run_agent`, and model-facing `document_id` routing — go
1255
+ through the new `executeDynamic()`, exactly as on the server.
1256
+ - **Unknown tools and role denials are results, not throws.** `execute()`
1257
+ returns `{ ok: false }` with `code: "unknown_tool"` or
1258
+ `"role_not_permitted"` instead of throwing; the new `tools.call()`
1259
+ throws a typed `ReviseToolError` for hosts that prefer exceptions.
1260
+ `ReviseRoleError` is still thrown by `agent.run()` and UI
1261
+ controllers.
1262
+ - **ID-keyed suggestion decisions return per-ID outcomes.**
1263
+ `review.acceptSuggestions`/`rejectSuggestions`,
1264
+ `review.acceptCommentSuggestions`/`rejectCommentSuggestions`, and
1265
+ `tools.acceptAllSuggestions`/`rejectAllSuggestions`, and the server
1266
+ session's `acceptSuggestions`/`rejectSuggestions` return
1267
+ `{ resolved, missing, unresolved }` (`ReviseSuggestionDecision`)
1268
+ instead of a bare count. Stale IDs land in `missing`; a role that may
1269
+ not resolve reports everything `unresolved`. `review.acceptAll()` /
1270
+ `rejectAll()` keep their boolean UI-gesture contract.
1271
+ - **Server sessions default to suggesting mode.** `createServerDocumentSession`
1272
+ without `mode` now proposes tracked changes instead of applying edits
1273
+ directly — the same default posture as the browser surface, and the safe
1274
+ one. Pass `mode: "editing"` (or per-call `directMode: true`) for
1275
+ direct application.
1276
+
1277
+ ### Added
1278
+
1279
+ - **Browser mutation results report created suggestion IDs.** Successful
1280
+ mutations carry `suggestionIds` — the tracked records that call created
1281
+ (empty for direct edits, `null` for read/search/measure tools) — with a
1282
+ concurrent human suggestion never attributed to the tool call. Feed them
1283
+ straight to `review.acceptSuggestions()`.
1284
+ - **The tool contract types ship from both entries.** `ReviseToolResult`,
1285
+ `ReviseToolResponse`, `ReviseToolFailure`, `ReviseToolError`,
1286
+ `ReviseSuggestionDecision`, the generated `ReviseToolInputMap`, and
1287
+ friends are exported by `@reviseio/sdk` and `@reviseio/sdk/backend`
1288
+ alike.
1289
+
1290
+ - **Server mutation results report the tracked records they created.**
1291
+ Successful mutation calls from `createServerDocumentSession` now carry
1292
+ `suggestionIds` — the tracked suggestion records that call created (empty
1293
+ for direct edits, `null` for read/search/measure tools) — so a host can
1294
+ persist per-edit IDs with its review workflow instead of diffing the
1295
+ document-global pending set.
1296
+ - **`listSuggestions()`** returns every pending suggestion as a reviewable
1297
+ record with authorship metadata (`authorType`, `agentName`,
1298
+ `agentModel`, `source`, `label`, `createdAt`), so hosts can decide on
1299
+ their own agent's suggestions and leave collaborators' pending work alone.
1300
+ - **`acceptAllSuggestions()` / `rejectAllSuggestions()`** make the
1301
+ whole-document decision an explicit, greppable call instead of the
1302
+ `acceptSuggestions(getPendingSuggestionIds())` idiom.
1303
+
1304
+ ### Fixed
1305
+
1306
+ - **Server tool types now resolve for `moduleResolution: "NodeNext"`
1307
+ consumers.** The packaged declarations re-exported the server tool contract
1308
+ through extensionless relative specifiers, which NodeNext cannot resolve —
1309
+ every tool input/output type silently degraded to `any`, and importing a
1310
+ contract type by name (e.g. `ServerDocumentSession`) failed to compile.
1311
+ The declarations now use explicit `.js` specifiers, which every supported
1312
+ resolution mode maps to the sibling `.d.ts` files.
1313
+ - **Importing a document with code blocks no longer risks crashing a Node
1314
+ host.** The canvas syntax highlighter tried to fetch its tree-sitter wasm
1315
+ under Node (the server DOM shims install a jsdom `window`, defeating its
1316
+ browser check), failing as an unhandled promise rejection. Highlighting now
1317
+ recognizes the server runtime explicitly and stays off, and a failed
1318
+ highlighter init in the browser no longer poisons later attempts.
1319
+ - **Table and list mutations no longer spam `Invalid access` warnings.**
1320
+ Building table rows, cells, and list items called Yjs `push()` on
1321
+ elements not yet integrated into a document, which logs a warning per
1322
+ child. Construction now inserts children at explicit indices — dozens of
1323
+ stderr lines per table insert in server logs, gone.
1324
+ - **Editing mode applies server edits directly again.** A server session in
1325
+ `"editing"` mode quietly recorded every mutation as a
1326
+ pending tracked suggestion instead of applying it. Editing-mode calls now
1327
+ run in the runtime's direct mode and settle within the call, matching the
1328
+ documented behavior; an explicit per-call `directMode` still overrides in
1329
+ either direction.
1330
+
1331
+ ## 0.9.0
1332
+
1333
+ ### Added
1334
+
1335
+ - **`review.listChanges()` now reports linked moves as moves.** A move pair
1336
+ surfaces as ONE `ReviseTrackedChange` with `kind: "move"`,
1337
+ `moveSourceBlockIds`/`moveDestinationBlockIds` locating each half, and
1338
+ `deletedText`/`insertedText` carrying the text as it left and as it
1339
+ arrived. Previously both halves were folded into a single change labeled
1340
+ `"delete"`, leaving a host review panel no way to distinguish a move from
1341
+ a replacement. Accept/reject semantics are unchanged: resolving the change
1342
+ settles both locations atomically.
1343
+
1344
+ ## 0.8.0
1345
+
1346
+ ### Added
1347
+
1348
+ - **Cut and paste now creates native linked moves in Suggesting mode.** Cutting
1349
+ text from supported paragraphs and pasting that same internal clipboard
1350
+ payload elsewhere in the document produces one atomic “Moved from”/“Moved
1351
+ here” pair. Accepting or rejecting either half resolves both locations, undo
1352
+ cannot strand an orphaned half, and DOCX export/reimport preserves native
1353
+ linked move markup. Copy/paste, editing mode, reused or mismatched clipboard
1354
+ payloads, and unsupported structural selections continue to use ordinary
1355
+ insertion/deletion behavior.
1356
+
1357
+ ## 0.7.0
1358
+
1359
+ ### Added
1360
+
1361
+ - **Server-side semantic tools.** `await createServerDocumentSession(ydoc,
1362
+ { documentId, mode })` in `@reviseio/sdk/backend` binds the canonical
1363
+ document-local agent tools — read, search, measure, mutate, layout,
1364
+ footnotes, tables, comments — to a host-owned Y.Doc under plain Node.
1365
+ `mode: "suggesting"` produces Word-compatible tracked changes with
1366
+ accept/reject; concurrent calls are serialized; literal tool calls infer
1367
+ their schema inputs and structured outputs. See the README's "Server semantic
1368
+ tools" section.
1369
+ - **Linked Word moves now round-trip as atomic move suggestions.** DOCX import
1370
+ pairs native `w:moveFrom` and `w:moveTo` ranges across runs, paragraphs,
1371
+ and table cells. Accepting either half keeps the text at its
1372
+ destination; rejecting either half restores its original location; export
1373
+ re-emits native paired move markup. Suggestion cards distinguish “Moved from”
1374
+ and “Moved here”, and focusing either half highlights its partner even across
1375
+ paragraphs.
1376
+
1377
+ ### Fixed
1378
+
1379
+ - **Node-side DOCX imports preserve tracked table-row revisions without a
1380
+ browser `FileReader`.** The backend DOM shims and table-revision
1381
+ postprocessor now work from `Blob.arrayBuffer()`, retaining row insertion
1382
+ and deletion metadata in server integrations.
1383
+ - **Word comment anchors preserve their identity and semantic range.** Safe
1384
+ native numeric IDs no longer shift, cross-paragraph and table-cell ranges
1385
+ emit one anchor triple instead of duplicates, and collapsed, overlapping,
1386
+ threaded, and resolved comments survive repeated round trips.
1387
+ - **Visible drawing text survives DOCX import when shape geometry is
1388
+ flattened.** Inline and anchored DrawingML, grouped shapes, legacy VML,
1389
+ headers, and standards-valid `mc:AlternateContent` Choice/Fallback content
1390
+ become editable paragraphs in reading order without duplicate fallback text.
1391
+ - **DOCX archives no longer inflate and large imports avoid repeated work.**
1392
+ Generated packages use DEFLATE compression, parse the main document XML once,
1393
+ and skip move indexing when a file has no moves, preventing the reported
1394
+ multi-fold output growth and superlinear no-move scan.
1395
+
1396
+ ## 0.6.0
1397
+
1398
+ ### Added
1399
+
1400
+ - **Horizontal rules and ornamental dividers are now supported throughout the
1401
+ editor.** Insert thin, thick, double, dashed, dotted, star, or diamond
1402
+ dividers from the toolbar or context menu, or create them with text triggers
1403
+ such as `---`, `===`, `-**-`, and `-<>-`. DOCX, HTML, Markdown, agent HTML,
1404
+ PDF, and plain-text output preserve the divider where the format permits;
1405
+ DOCX, HTML, Markdown, RTF, and ODT imports recognize their native divider or
1406
+ paragraph-border representations.
1407
+
1408
+ ### Changed
1409
+
1410
+ - **Em-dash autocorrection now waits for a word boundary.** Typing `--` remains
1411
+ literal until Space or Enter, allowing `---` to be used for horizontal-rule
1412
+ insertion and preserving word-initial values such as `--flag`.
1413
+
1414
+ ### Fixed
1415
+
1416
+ - **Words no longer wrap in the middle at formatting or tracked-change run
1417
+ boundaries.** A word split across differently styled text nodes now wraps as
1418
+ one unit and keeps a stable layout when suggestions are accepted.
1419
+ - **Suggestion editing produces stable runs and caret placement.** Continued
1420
+ typing or backspacing merges into the existing suggestion instead of creating
1421
+ one run per keystroke, replacement normalization no longer leaves the caret
1422
+ inside hidden deleted text, and Enter after a pending deletion creates the
1423
+ expected paragraph or list item without moving the deleted content.
1424
+ - **Structural editing keeps the expected document shape and keyboard focus.**
1425
+ Backspace exits or splits empty list items correctly, compatible lists rejoin
1426
+ when their separating empty paragraph is removed, Enter at the start of a
1427
+ leading heading or code block creates a body paragraph above it, and toolbar
1428
+ commands no longer steal keyboard focus from the editor.
1429
+
1430
+ ## 0.5.1
1431
+
1432
+ ### Fixed
1433
+
1434
+ - **PDF table-of-contents page numbers stay accurate when a heading moves to
1435
+ the next page.** Export now records a heading's destination after paragraph
1436
+ pagination, so a keep-with-next or end-of-page preflight cannot leave the
1437
+ TOC pointing at the page the heading would have occupied before it moved.
1438
+
1439
+ ## 0.5.0
1440
+
1441
+ ### Added
1442
+
1443
+ - **Comments now work on list items, including nested items.** Selecting list
1444
+ text, expanding a word from the caret, and commenting on a whole item all
1445
+ create item-local anchors. Returning the caret to that text activates the
1446
+ thread, list-item threads survive agent-HTML round trips, and the
1447
+ `leave_comment` agent tool accepts list-item IDs.
1448
+
1449
+ ### Changed
1450
+
1451
+ - **PDF export now follows the editor's layout and print semantics much more
1452
+ closely.** It shares wrapping and pagination rules for tab stops and
1453
+ leaders, hyphenation, keep-with-next, keep-lines, widows and orphans, code
1454
+ blocks, nested tables, footnotes, page and section breaks, live TOC page
1455
+ numbers, line numbers, and watermarks. Editor-only placeholders and review
1456
+ chrome are not printed, and Word hidden text remains hidden in ordinary PDF
1457
+ output. The SDK now carries its metric-compatible PDF fonts itself, so an
1458
+ embedding host does not need to mirror Revise's public font directory.
1459
+ - **Agent tool sessions reject redundant full-document read loops.** After a
1460
+ session has read the complete document, another sequential `read_document`
1461
+ returns `no_new_read_context`; agents can still revisit known content with
1462
+ `read_specific_blocks`.
1463
+
1464
+ ### Fixed
1465
+
1466
+ - **DOCX formatting exceptions survive a complete edit and export cycle.**
1467
+ Explicit run-property clears over named styles, zero paragraph indents,
1468
+ paragraph border and shading clears, decimal font sizes, and mixed small-cap
1469
+ and all-cap overrides now remain distinct from inherited formatting and do
1470
+ not leak into adjacent text.
1471
+ - **Complex Word structures no longer lose modeled content on re-export.**
1472
+ Internal bookmark links stay internal; exact table widths, columns,
1473
+ alignment, cell padding, and vertical alignment survive; nested tables keep
1474
+ the paragraphs around them; display equations are not flattened when a file
1475
+ is immediately re-exported; and multi-block footnotes and endnotes can retain
1476
+ their lists and tables.
1477
+ - **Accepting or rejecting a compound agent edit is atomic.** Mixed text,
1478
+ formatting, and structural suggestions are resolved together, so accepting
1479
+ a rewrite no longer retains deleted fragments and rejecting it restores the
1480
+ original content and formatting.
1481
+ - **Comment cards stay where users put them.** A previously active card no
1482
+ longer drifts with the viewport, and selecting text inside a card no longer
1483
+ jumps focus back to the document or clears the selection. Inline code in
1484
+ comment bodies is also styled as code.
1485
+ - **Package managers can no longer omit the Yjs runtime.** Every editor session
1486
+ is Yjs-backed even without a collaboration provider, so `yjs` and
1487
+ `y-protocols` are now required peers instead of optional peers. This makes
1488
+ package managers install or validate them instead of letting bundlers
1489
+ substitute empty optional-peer modules and fail the consumer build.
1490
+
1491
+ ## 0.4.5
1492
+
1493
+ ### Fixed
1494
+
1495
+ - **Starting a list no longer drops the font.** Typing a list trigger
1496
+ (`- `, `1. `, `[] `) in a paragraph set in a non-default font produced
1497
+ a list item that fell back to the default font: clearing the trigger text
1498
+ left an empty item with nowhere to carry its formatting. The formatting at
1499
+ the trigger's trailing edge — the font family included — is now preserved
1500
+ on the empty item and applies to the next character typed.
1501
+
1502
+ ## 0.4.4
1503
+
1504
+ ### Fixed
1505
+
1506
+ - **Suggestion cards now hang from the suggested text.** The floating
1507
+ accept/reject card anchored to the caret; it now follows the suggested
1508
+ fragment (or your selection) and sits centered below its line, the same
1509
+ placement the revise.io app uses, falling back to the caret only when the
1510
+ fragment cannot be measured. Wide cards are clamped to the page edges
1511
+ instead of a fixed margin.
1512
+
1513
+ ## 0.4.3
1514
+
1515
+ Identical in content to 0.4.2; republished.
1516
+
1517
+ ## 0.4.2
1518
+
1519
+ ### Fixed
1520
+
1521
+ - **Word-level diffs misplaced edits next to repeated words.** When the text
1522
+ adjacent to an edit repeated a word from the edit itself (replacing
1523
+ "[Berkshire County / appropriate Massachusetts county]," with "Suffolk
1524
+ County, Massachusetts," just before "Massachusetts will"), the unchanged
1525
+ suffix could be drawn as deleted and retyped. Unchanged repeated words now
1526
+ stay anchored as unchanged, in tracked changes and the diff view alike.
1527
+ - **Writing a comment no longer collapses the comments margin.** Finishing a
1528
+ draft that had itself opened the margin always collapsed it — even when
1529
+ submitting had just created a thread, so the pages jerked sideways in both
1530
+ directions and hid the card the user just wrote. The margin now stays open
1531
+ on the new thread; only an abandoned draft with no other open thread
1532
+ collapses it.
1533
+ - **Comment card placement around drafts and tracked changes.** A comment
1534
+ draft started while hovering the card stack could pin its card — and drag
1535
+ the viewport — to the top of page 1; it now anchors where the draft was
1536
+ made. A caret inside a resolved thread's highlight, or inside an imported
1537
+ thread's replies, activated no card at all; it now activates the right
1538
+ open thread. And when a commented paragraph also contains tracked changes,
1539
+ the card describes the change under the cursor instead of jumping to the
1540
+ top of the paragraph.
1541
+ - **The selection card no longer chases the pointer mid-drag.** While the
1542
+ mouse button is down nothing pops up under the pointer; the card appears
1543
+ on release, anchored below the selection the user meant.
1544
+
1545
+ ## 0.4.1
1546
+
1547
+ ### Fixed
1548
+
1549
+ - **Opening the export menu crashed.** An icon component in the export menu
1550
+ referenced React without importing it, which the packaged build has no
1551
+ global to fall back on.
1552
+
1553
+ ## 0.4.0
1554
+
1555
+ ### Changed
1556
+
1557
+ - **The default entry no longer ships Tree-sitter syntax highlighting or the
1558
+ embedded WASM payload.** Code blocks still render as code, and every WASM
1559
+ hot path has a TypeScript implementation. This keeps the normal
1560
+ integration smaller and compatible with strict Content Security Policies.
1561
+ Optional features now load as async chunks inside the package.
1562
+
1563
+ ### Added
1564
+
1565
+ - **`@reviseio/sdk/full`** — an opt-in entry point that keeps token-colored
1566
+ code blocks and the WASM hot paths. The API and stylesheet are identical
1567
+ between the two entries.
1568
+
1569
+ ## 0.3.4
1570
+
1571
+ ### Fixed
1572
+
1573
+ - **The SDK no longer attempts any telemetry.** Earlier builds emitted
1574
+ editor health metrics toward a Revise backend that does not exist in your
1575
+ deployment, which could only fail — loudly, as console CORS errors — and
1576
+ represented network calls you never asked for. Telemetry is now something
1577
+ only the revise.io application itself can switch on; embedded editors
1578
+ send nothing anywhere: no metric POSTs, no analytics vendor code, no
1579
+ beacons.
1580
+
1581
+ ### Added
1582
+
1583
+ - **`onAnalyticsEvent`** — the editor's own instrumentation, delivered to
1584
+ the host instead:
1585
+ `<ReviseEditor onAnalyticsEvent={(event, properties) => ...} />`.
1586
+ Forward events to your own analytics service; a throwing handler never
1587
+ breaks the editor. Event names and property shapes are internal and
1588
+ version-unstable.
1589
+
1590
+ ## 0.3.3
1591
+
1592
+ Four suggesting-mode fixes, two of them content corruption. If your users
1593
+ edit in `suggesting` mode — the mode this SDK exists for — take this
1594
+ release.
1595
+
1596
+ ### Fixed
1597
+
1598
+ - **Pasting in suggesting mode corrupted the document.** The paste path
1599
+ predated suggesting mode: it duplicated the rest of the paragraph and
1600
+ inserted the pasted text without tracked-change marks, so the paste was
1601
+ invisible to review and survived reject. Pasting is now recorded exactly
1602
+ as if the pasted characters had been typed — an insertion suggestion, plus
1603
+ a deletion suggestion for any replaced selection.
1604
+ - **Formatting across a pending change destroyed it.** Applying bold (or any
1605
+ inline format) over a range touching a pending insertion or deletion
1606
+ overwrote the change's identity; resolving the format then silently turned
1607
+ a pending insertion into accepted text, or resurrected deleted text.
1608
+ Formatting now leaves deletion spans alone, folds into insertion spans (as
1609
+ Word nests run properties inside `w:ins`), and records a reviewable
1610
+ format change only on unmarked text.
1611
+ - **Accepting a deletion that crossed a paragraph boundary left the
1612
+ paragraphs unmerged.** The boundary is now part of the suggestion, as the
1613
+ pilcrow is in Word: accepting merges the paragraphs, in any resolution
1614
+ order, for any number of paragraphs in the selection.
1615
+ - **Copying a selection inside your own pending insertion copied nothing.**
1616
+ It now copies the selected text. Clipboard payloads are also sanitized so
1617
+ tracked-change marks never travel with copied content.
1618
+
1619
+ ### Console
1620
+
1621
+ - Opening a document no longer logs to the console (previously one Yjs
1622
+ warning per block plus two internal debug lines). `console.warn` and
1623
+ `console.error` remain for genuinely actionable problems.
1624
+
1625
+ ## 0.3.2
1626
+
1627
+ ### Fixed
1628
+
1629
+ - `editor.whenReady()` was missing from the published type declarations. It
1630
+ worked at runtime, but TypeScript rejected the call the documentation tells
1631
+ you to make.
1632
+
1633
+ ## 0.3.1
1634
+
1635
+ ### Fixed
1636
+
1637
+ - Using the editor handle from `onReady` no longer throws. `onReady` fires
1638
+ before any document exists, and "subscribe to everything on ready" is the
1639
+ first thing a host writes — a subscription placed then now waits and
1640
+ attaches when a document arrives. `selection.observe()` was affected too.
1641
+ Methods that act on a document still fail loudly, and the message now names
1642
+ the fix.
1643
+
1644
+ ### Added
1645
+
1646
+ - `editor.whenReady()` — resolves once a document is open and its
1647
+ controllers are usable.
1648
+ - `REVISE_SDK_VERSION` and `REVISE_SDK_BUILD` exports, and a `bugs` entry
1649
+ in the manifest: a support ticket can name the exact build it came from.
1650
+
1651
+ ## 0.3.0
1652
+
1653
+ ### Collaboration
1654
+
1655
+ Multi-user editing over a Yjs transport you own. The editor builds the
1656
+ document; you attach the connection:
1657
+
1658
+ ```ts
1659
+ collaboration: {
1660
+ connect: (doc, awareness) =>
1661
+ new HocuspocusProvider({ url, name, document: doc, awareness }),
1662
+ synced,
1663
+ }
1664
+ ```
1665
+
1666
+ Remote carets, a presence roster (`editor.collaboration`), seed-or-join
1667
+ semantics, and validation of any document you supply. See the collaboration
1668
+ guide.
1669
+
1670
+ ### Roles
1671
+
1672
+ `role="editor" | "suggester" | "viewer"`, editor-wide or per document, and
1673
+ enforced on every surface: typing, the built-in chrome, the handle, and agent
1674
+ tool calls. A suggester cannot leave suggesting mode, apply anything directly,
1675
+ or accept and reject.
1676
+
1677
+ ### Tracked changes you can list
1678
+
1679
+ `review.listChanges()` and `review.getChange(id)` return each pending change
1680
+ with its kind, author, timestamp, affected blocks, and text — enough to build
1681
+ your own review panel. Imported Word redlines keep their original reviewers.
1682
+
1683
+ ### Server-side primitives
1684
+
1685
+ New subpath export `@reviseio/sdk/backend` (Node only): `parseDocument`,
1686
+ `fileToYDoc`, `seedYDocFromFile`, `ydocToDocx`, `encodeYDoc`/`decodeYDoc`.
1687
+ Your server can create a collaborative room from a .docx before any browser
1688
+ connects, and export a live room without one. Requires `jsdom`.
1689
+
1690
+ ### Breaking
1691
+
1692
+ - **`yjs` and `y-protocols` are now peer dependencies** and are no longer
1693
+ bundled. Install them yourself, and make sure your bundler resolves ONE copy
1694
+ — Yjs identifies its own types with `instanceof`, so a second copy breaks a
1695
+ shared document. Only collaboration needs them; they are optional peers.
1696
+ - **`ReviseDocumentInput.docx` is now optional**, since a document joining a
1697
+ collaborative room needs no source file. Inputs must supply `docx`,
1698
+ `collaboration`, or both.
1699
+
1700
+ ### Fixed
1701
+
1702
+ - `search_result_id`, which the agent tool schemas advertise for bulk edits,
1703
+ was unusable: tool state did not survive between `tools.execute()` calls.
1704
+ - `exportDocx()` omitted TOC page numbers, which only the live layout knows.
1705
+ - Exports lost imported named styles and reset core property dates in any
1706
+ non-browser environment.
1707
+ - `collaboration.synced` was read once at mount, so a host reporting sync
1708
+ later was ignored and the document never opened.
1709
+ - The margin insert-comment chip was missing from the embedded editor.
1710
+ - Presence colors: an explicit `currentUser.color` was ignored whenever the
1711
+ user had an id.
1712
+
1713
+ ## 0.2.0
1714
+
1715
+ Multi-document sessions, host-owned chrome, skinning props, per-embed
1716
+ theming, the selection controller, and comment-thread agents.
1717
+
1718
+ ## 0.1.0
231
1719
 
232
- - **The editor entry points of 2.x.** `revise/editor`, `revise/editor/full`,
233
- and `revise/server` now throw an error pointing to `@reviseio/editor`, and
234
- `revise/style.css` is an empty stylesheet that says the same.
1720
+ First release: the editor, DOCX in and out, tracked changes, comments, and
1721
+ the agent tool surface.