> ## Documentation Index
> Fetch the complete documentation index at: https://revise.io/developer/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release history for @reviseio/editor (formerly revise and @reviseio/sdk).

## 2.3.0

### Added

* **`toolbarMode="compact"`.** The everyday part of the ribbon, centered,
  for narrow fixed-width hosts (about 760px): undo and redo, font, size,
  styles, paragraph, links, indents, lists, Find, and Export. The clipboard,
  Insert, and Print are left out.
* **`toolbarMode="floating"`.** The full ribbon as a centered card over the
  canvas, the way the Revise app shows it.
* **`onImportFile`.** Shows Import before Export in the ribbon (a file picker
  for DOCX, ODT, RTF, Markdown, HTML, text, and XML) and accepts files
  dropped anywhere on the editor, with a "Drop to import" overlay. Image
  drops still insert images. The host receives the file and decides what
  importing means.
* **Header and footer images.** Logos in Word headers and footers now show
  on the page and in PDF export. They were kept for DOCX round trips but
  never drawn. Images are scaled down to fit the margin band and never
  overlap body text. `set_header_footer` takes an `image` (`image_id` of an
  image already in the document, with `zone`, `alt`, `width`, and `height`)
  and a one-based `sectionIndex` to edit one section's own header or footer.
  Concurrent edits to different bands' images merge instead of overwriting
  each other. DOCX export keeps the logo's alignment. It turns on Word's
  first-page or odd/even headers when a logo needs them, and leaves a logo
  out of sections whose margin is too small to show it.
* **`@reviseio/editor/server`: `agentName`.**
  `createServerDocumentSession({ agentName })` sets the author on the
  suggestions and comments the session's tools create, which DOCX export
  writes as `w:author`. Defaults to "Revise Agent".
* **The delegated agent can move any block** as one tracked move: images,
  code, equations, horizontal rules, page breaks, and tables of contents as
  well as paragraphs, lists, and tables. Section breaks are still refused.

### Changed

* **The package is now `@reviseio/editor`.** It was published as `revise`
  through 2.2.0. The editor, license, and API are unchanged; only the import
  paths move: `revise/editor` → `@reviseio/editor`, `revise/editor/full` →
  `@reviseio/editor/full`, `revise/server` → `@reviseio/editor/server`,
  `revise/style.css` → `@reviseio/editor/style.css`, and the `revise` root
  (build identity) → `@reviseio/editor/version`. The docs moved to
  [revise.io/developer/docs](https://revise.io/developer/docs/editor-sdk/introduction).
* **`replace_block` and `remove_blocks` name a range by its last block.**
  `end_id` (inclusive, same container as `id`) replaces `count` in the tool
  definitions and in `ReviseToolInputMap`. Calls with `count` still run, but
  TypeScript callers that pass it need `end_id`. A reversed, unknown, or
  cross-container range fails with `invalid_block_range` before anything
  changes.
* **`remove_table_rows` replaces `remove_table_row`.** It removes one or more
  rows per call, named by stable row ID (`rowIds`, a string or an array).
  Rows the agent read stay removable after other rows change, without
  reading the table again. `remove_table_row` with `{ tableId, rowIndex }`
  is still accepted.
* **`read_table` `mode: "cell_text"` pages list their nested blocks**
  (`blocks`: block ID and text offset), and each nested block's text opens
  with an inline `[[block_id]]` marker. Text inside an oversized cell can be
  read with `read_specific_blocks` and edited. A `replace` aimed at a table,
  row, or cell edits the one nested block that contains the text.
* **`set_header_footer` reports what actually changed.** `clear: true`
  without `slot` or `sectionIndex` removes that side from every page and
  section. A call that changes nothing fails with "No changes detected" and
  the current header/footer listing. An unknown `slot` is an error instead
  of widening a clear. Clearing the first-page or even-page slot while the
  document-wide footer shows there leaves an empty slot that hides it, as in
  Word. `search_document` also matches header and footer text.
* **Mutation tools refuse empty arrays** (`content`, `replacements`,
  `cells`, `ids`, `rowIds`, style `attrs` or `selectors`) before changing
  anything, and name the tool that fits instead. The definitions mark these
  `minItems: 1`. Empty table-insert content still inserts empty cells.
* **Edits next to an unresolved paragraph split or merge are refused** with
  `pending_paragraph_boundary`: accept or reject the split first. Such edits
  used to lose or duplicate text on review.
* **`style_blocks` headings take the document's heading style.** In an
  imported Word document, a paragraph made a heading gets the heading
  style's spacing and run formatting, and exports like the document's other
  headings.
* **Agent-inserted content follows the surrounding font.** Inserted tables
  take the font and body size at the insertion point. One `insert_block`
  call uses one font for all its pieces. Rows and columns added by
  `insert_table_row` and `insert_table_column` keep the table's font. A
  heading's size no longer carries into paragraphs inserted after it. Cells
  holding only inline markup (`<td><b>Total</b></td>`) keep their
  formatting. Tables inserted from the editor take the caret's font.
* **DOCX export keeps more of the original file.** Untouched table rows,
  cells, and list items are written as the original bytes when a neighbor
  changes. Paragraphs with only text edits keep their original paragraph
  properties. The original `styles.xml` is kept, with only the missing style
  definitions added. Opening a document with page numbers no longer forces
  headers, footers, and styles to be regenerated. In
  `@reviseio/editor/server`, `exportDocument(room, { mode: "final" })` to
  .docx keeps untouched content as the original bytes too.
* **The delegated agent** (`agent.run()` and comment agents) sees the
  document's headers and footers. It stays inside a locked user selection
  unless asked to go wider. It may re-read blocks it has already read. It
  puts content asked to be added into the document rather than only in
  chat, and it no longer finishes before results it asked for arrive. With
  Anthropic models, requests that follow edits keep the prompt cache.

### Fixed

* **Comment cards sit beside the page**, as in the Revise app, instead of
  at the far right edge of a wide editor.
* **The ribbon stays centered on the pages** when the comments margin moves
  them aside, as far as its width allows.
* **Add Comment and Toggle Comments** in the Review ribbon work. They were
  always disabled.
* **Find shows in the native ribbon.** It was hidden whenever Dictate was,
  which the SDK always hides.
* **The ribbon keeps text color and the styling menu down to 352px**, where
  they were dropped below 430px.
* **The selection stays visible, dimmed, when focus leaves the editor**, for
  example to a chat input in the host page, instead of disappearing.
* **Copy and Cut work in iframes that deny clipboard access** (no
  `clipboard-write` permission).
* **Agent avatars on suggestion cards load**, where they used to resolve
  against the host page's origin and show a generic avatar.
* **Hovering Accept all or Reject all previews the decided document.** Blocks
  the decision removes, such as a moved table's source, are hidden, while
  edited code and math blocks stay. Typing ends the preview, so keys never
  edit a hidden block.
* **Word redlines with inserted or deleted paragraphs accept and reject
  fully.** Consecutive paragraph-mark revisions used to overwrite each
  other, so rejecting inserted clauses left them in place and accepting
  could leave an empty paragraph. Rejecting a split keeps the paragraph's
  current text, formatting, and pending revisions. Settling a
  paragraph-formatting change no longer undoes later inline decisions.
  Accept all and Reject all finish in one call when one decision uncovers
  another.
* **Tracked table changes export to Word as revisions.** A suggested row
  insertion, alone or combined with cell edits, is a Word row revision with
  attributed inline cell changes instead of an untracked table. A
  repeating header row survives a tracked deletion of the first row.
* **Moves of images, code, equations, rules, page breaks, and tables of
  contents export once** to DOCX, not as two copies. Accepting or rejecting
  a moved table with code or math in its cells no longer leaves a damaged
  copy. Copied content no longer carries suggestion records.
* **A DOCX export never brings back a removed paragraph** (for example, a
  rejected insertion) by returning the original file unchanged.
* **Highlight colors map by hue.** Office tints such as lavender no longer
  show as gray, and mid or dark neutrals no longer show as green or yellow.
  `style_blocks` can restore a block's original highlight.
* **PDF export draws SVG images** instead of blank space, and fetches an
  image used on every page once.
* **HTML input with `<!-- comments -->`** no longer fails, and loose text
  before a block keeps its place.
* **Turning page numbers off keeps an empty first-page footer**, so the
  footer stays hidden on page 1.
* **Footnote edits.** Text in a just-inserted footnote is edited in place
  instead of moving into the body. A find matches only visible footnote
  text, not pending deletions. A batch that includes a footnote edit fails
  or succeeds as a whole. `leave_comment` accepts a footnote that was read.
* **`replace` batches apply as planned.** Chained steps
  (`Alpha→Beta`, `Beta→Gamma`), finds over a `search_result_id`, and
  id-less `occurrence: "all"` finds are checked against each block's text
  as earlier steps leave it. A step no longer lands on the wrong block or
  sentence. Errors say when a long find drifts from the block, when the
  block already contains the replacement, and that none of a failed call's
  replacements applied.
* **`read_specific_blocks` reads a list item inside a table cell.**
* **NEL, LS, and PS characters read as spaces**, so a find copied from a
  read matches.

## 2.2.0

### Added

* **ODT and RTF input.** `ReviseDocumentFormat` and `ReviseServerFormat` gain
  `"odt"` and `"rtf"`, detected from `.odt` / `.rtf` filenames and from the
  `application/vnd.oasis.opendocument.text`, `application/rtf`, and
  `text/rtf` MIME types. Both import fonts, sizes, colors, highlighting,
  character and paragraph formatting, headings, lists with their numbering,
  tables with merged cells and column widths, images, hyperlinks, footnotes
  and endnotes, headers and footers, comments, tracked changes, and page
  size and margins. RTF from Word, WordPad, TextEdit, and LibreOffice is
  supported, in any Windows code page or East Asian encoding. Each converter
  loads only when a host first opens that format. `revise/server`'s
  `parseDocument`, `fileToYDoc`, and `seedYDocFromFile` accept both. Host
  code with an exhaustive `switch` over either type needs cases for the two
  new values.
* **Delete whole table rows, columns, or tables from a cell selection.**
  Backspace or Delete over fully selected rows or columns removes them, and
  over every cell removes the table; a partial selection still clears only
  the cell contents. Removing several rows is one undo step, and a table that
  was the only block leaves an empty paragraph. Shift+click in another cell
  of the same table now extends a cell selection, as dragging does.
* **Move connectors.** When a tracked move is focused, a line in the left
  margin links where the text moved from to where it moved to, across pages.
  It is not drawn in print preview.
* **Pleading-paper line numbers.** Documents whose page layout carries a
  pleading grid show numbered rows (for example 1 to 28) at fixed positions
  on every page, independent of the text, on screen and in PDF export. DOCX
  export writes them as Word line numbers restarting on each page.

### Changed

* **Margin line numbers behave like Word's.** Each number sits on its line's
  baseline, table lines are not counted on screen (PDF already skipped
  them), and a section that turns numbering off shows none instead of
  inheriting the document setting. Numbers are set in the font that
  dominates each page's text, on screen and in PDF, where they were always
  Helvetica before.
* **The delegated agent can move blocks.** `agent.run()` and comment agents
  can move paragraphs, lists, and tables as one tracked move (applied
  directly in editing mode); blocks with anchored comments are not moved.
  `move_blocks` is not part of the embedded tool list for `tools.*` hosts.
  The delegated agent also recovers more reliably: it repairs a run that
  edited and then reported no change, checks table fill work before it
  finishes, and keeps the request and latest tool results when it recovers
  from a context limit.
* **Suggestion cards show a date once a change is over a week old.** Old
  changes read "Sep 4" or "Oct 11, 2013" instead of "4739d ago".
* **The footnote card is a compact row.** Clicking a footnote reference shows
  its label with **Go to note** and **Remove**; the note is edited in the
  note itself. In narrow layouts the card is centered under its reference
  mark.

### Fixed

* **Links.** Bare email addresses link and autolink as `mailto:`;
  `mailto:` and `tel:` URLs are kept as typed; an `@` before the path is not
  read as `https://` user info. Cmd+K uses the selected text as the link
  target only when it is a full URL or an email address, and the link popup
  finds a link Cmd+K just made on a backward selection.
* **Link, footnote, and inline-math popups line up at every zoom level.**
* **Math is no longer clipped when it renders before the KaTeX fonts load.**
  Such results show provisionally and re-render once the fonts arrive, and
  failed font or stylesheet fetches are not cached.
* **DOCX tracked moves of whole paragraphs, lists, and tables.** On import,
  Word's paragraph-mark `w:moveFrom` / `w:moveTo` make the whole block part
  of the move, so accepting it removes the source paragraph instead of
  leaving an empty one, and a list split across a move becomes two lists.
  Export writes paragraph marks and table rows with the move, and accepting
  or rejecting resolves both halves together.
* **Accepting the deletion of every row of a table removes the table**, as
  in Word, instead of leaving a table with no rows.
* **DOCX header and footer line breaks.** `w:br` in headers and footers is
  imported, and export writes `w:br` instead of a raw newline that Word
  showed as a space.
* **Header and footer layout.** In multi-column sections, headers and
  footers span the full text width instead of one column; a zone is as wide
  as its widest line; a bordered zone, such as a footer rule, spans the whole
  band; and empty zones give up their space.
* **`replace_block` and `append_to_paragraph` on a non-text target**, such as
  a table, fail with `target_type_mismatch` instead of doing nothing.
* **DOCX, ODT, and RTF open where `Blob.arrayBuffer` is missing** (Safari
  before 14, jsdom). Files are read with a `FileReader` fallback.

### Security

* **ODT and RTF import is hardened against hostile files.** Links pass a
  scheme allowlist (http, https, mailto, tel, ftp, and relative), so
  `javascript:` and similar are dropped. Self-referencing ODT deletions and
  RTF control words such as `\constructor` can no longer overflow the stack
  or swallow text, and imported tables are capped at 1,000 columns and
  100,000 cells.

## 2.1.0

### Added

* **`source` on document inputs.** `{ id, source: file }` names the field for
  what it takes: DOCX, Markdown, plain text, or HTML. `docx` still works as the
  same field; passing both with different values throws.

* **`context_notes` is optional in typed host calls.** `tools.execute()` and
  `tools.call()` (browser and `revise/server`) fill in `"N/A"` for the read and
  search tools, so application code no longer passes a model's working memory.
  `executeDynamic()` keeps the schema requirement for model-provided calls.

* **`leave_comment` reports a retargeted anchor.** When the anchor text is not
  in the named block and the comment goes to the only read block that has it,
  `data.requestedBlockId` names the block you asked for and the message says so.

* **`read_table` and `edit_table_cells` agent tools.** Read a large table in
  bounded windows (a summary, up to 50 rows, or one oversized cell in pages),
  then set the plain text of up to 50 cells per call by row ID and column.
  Cell text is written literally. Only cells a `read_table` call returned in
  full can be edited, and that read stays valid across later `execute()` calls
  on the same document while the cell and table geometry remain unchanged.
  An invalid target rejects the whole batch with no changes. In suggesting mode each cell is its own suggestion. Read-only
  surfaces and viewers get `read_table` only. Both tools are also in the
  `revise/server` session. The SDK's `read_table` does not take the native
  agent's task-declaration arguments (`task_kind`, `scope_*`,
  `source_attachment_id`, `deliberate_blanks`). They are left out of the
  published schema, and a call that supplies one fails with
  `unsupported_argument` without reading anything. Empty placeholders
  (`null`, `""`, `[]`) are ignored.

### Changed

* **The delegated agent plans long tasks.** `agent.run()`, `revise_run_agent`,
  and comment agents keep a step-by-step plan for multi-step work, update it
  in the same turns as their edits, and save it with the conversation, so
  fewer turns go to bookkeeping. The embedded tool list is unchanged: plan
  tools stay inside the delegated agent.
* **Faster on long documents.** The scrollbar track and its markers are drawn
  once and reused while scrolling, Find reuses each block's normalized text
  between keystrokes, and tracked-change records are indexed in one pass
  instead of one document walk per suggestion.

### Fixed

* **DOCX paragraph spacing follows the document's rules.** `w:contextualSpacing` no longer
  zeroes a paragraph's declared space before and after on import. Spacing is
  resolved from neighboring paragraphs on screen, in table cells and
  containers, and in PDF export: the gap between two paragraphs is the larger
  of their spacings, not the sum, and contextual spacing drops it only between
  paragraphs of the same style. PDF keep-with-next reserves the whole gap, and
  exported DOCX keeps the declared spacing. Documents whose paragraphs both
  declare spacing lay out tighter than in 2.0.x.
* **`style_blocks` with `list-style-type: none` turns list items into plain
  paragraphs**, keeping their spacing and line spacing and applying the call's
  other paragraph attributes in the same step.
* **Unsupported DOCX content can be suggested for removal.** In suggesting
  mode, removing a block the editor preserves but cannot render (an opaque
  DOCX payload) now becomes a tracked deletion.
* **Comment previews keep their layout.** In a comment chip's hover preview,
  the avatar holds its size and a long author name is truncated.
* **An editor with no agent configured sends nothing.** `agent.run()`, the
  `revise_run_agent` tool, and comment agents used to stream the document,
  unauthenticated, to Revise's hosted agent and then report a generic
  connection error. Without a `turnStream`, `baseUrl`, or `token`, they now
  fail at once with `agent_not_configured` (`AgentNotConfiguredError` from
  `agent.run()`), and `getToolDefinitions()` leaves the delegation tool out.
* **`documents.open()` activates the new document every time.** Opening a
  document straight after another open, or after `documents.activate()`, left
  the earlier one active. `documents.list()` status was also briefly stale
  right after a document became ready.
* **`tools.getDefinitions()` lists only the native tools.** It included
  `revise_run_agent`, which the docs say it leaves out.
* **Changing `agent.turnStream` no longer reloads the document.** A new
  `turnStream` or `disableMetrics` value re-created the document runtime,
  re-parsing the source and dropping unsaved edits, so an inline generator in
  JSX reloaded the document on every render. Agent settings now apply to the
  next run in place.
* **Reads are not refused for the life of the editor.** After a window had
  been read once, every later `read_blocks_from_index` of it failed with
  `no_new_read_context`, so a host agent's second conversation could not read
  the document. The guard now resets with each call, like the other per-turn
  limits.
* **Tool errors speak to SDK callers.** Messages no longer carry the internal
  `Failed operation: <tool>: <Error>:` prefix or point at `<document_content>`,
  which only Revise's own agent sees; they point at read results instead.
* **The open-error screen shows a plain message.** A corrupt file showed the
  parser's internals (a zip library's message and link) to the person who
  picked it. `onError` still receives the full detail. Loading text no longer
  says "DOCX" for other formats, and a `File` source's title drops `.md`,
  `.txt`, and `.html` extensions as well as `.docx`.
* **PDF export requests a failing font once.** When a font download failed
  (a CSP or firewall blocking revise.io, say), export requested the same URL a
  second time. The warning now says a fallback font was used and names
  `setAssetBaseUrl()` for mirroring the fonts.
* **Readable errors from the package in Node.** Bundled code is wrapped at
  short lines, so an uncaught error (such as the missing-`jsdom` hint) is no
  longer printed under a 100 KB line of minified source.
* **Quieter host builds.** Vite no longer warns that `"buffer"` was
  externalized, or prints the inlined WebAssembly's base64 as a file that
  "doesn't exist at build time".

## 2.0.1

### Added

* **`tools.export({ format, mode })`.** Export as DOCX, PDF, HTML, Markdown,
  or plain text from code, not just the ribbon's Export menu. `mode: "final"`
  accepts every pending change and drops comments first for a clean copy;
  the default `"review"` keeps tracked changes and comments in a .docx. The
  editor-level `tools.export(options, documentId?)` routes to any open
  document.
* **`exportDocument(source, options)` in `revise/server`.** The same export
  for a room or a parsed document on the server: DOCX, HTML, Markdown, and
  plain text, in review or final mode.
* **`onImageUpload(file, documentId)`.** Store images users insert, paste, or
  drop in your own storage and return the URL the document should use.

### Fixed

* **Inserting, pasting, or dropping an image works.** It used to post to
  Revise's app API, which the SDK cannot reach, so the image never appeared.
  Without `onImageUpload`, images are now embedded in the document as data
  URLs and export into the .docx. `toolbar.insertImage()` resolves `false`
  when an upload fails, and the failure reaches `onError`.
* **Docs:** linked moves are described correctly in Support, the reserved
  collaboration keys point to `RESERVED_DOCUMENT_KEYS`, and the delegated
  agent page says how to get hosted-agent access.

## 2.0.0

The SDK is now public: `npm i revise`. No account, token, or contact
with us is needed to install it. 2.0.0 also ships everything from the
2.0.0-alpha releases below.

### Changed

* **BREAKING: the package is now `revise`.** The private `@reviseio/sdk`
  package is retired. Update the dependency and imports:
  `@reviseio/sdk` → `revise/editor`, `@reviseio/sdk/full` →
  `revise/editor/full`, `@reviseio/sdk/backend` → `revise/server`, and
  `@reviseio/sdk/style.css` → `revise/style.css`. Remove the `@reviseio`
  scope and token lines from `.npmrc`.
* **New license: free for evaluation, personal projects, and education.**
  Production use by businesses, nonprofits, and government requires a paid
  license. See `LICENSE` and [developer.revise.io](https://developer.revise.io/editor-sdk/license).
  The previous 60-day evaluation terms no longer apply.
* **The editor fills its container at any size.** The 640×560px minimum is
  gone, so the editor fits phone-width columns and short panels without
  overflowing them. A container with no height gets a 560px fallback and a
  one-time console warning instead of a collapsed editor.
* **Hosted agent defaults to production.** Without `agent.baseUrl`, the
  delegated Revise agent now targets `https://agent.revise.io` instead of a
  development address.

### Added

* **A 4.5 MB package, with assets loaded on demand.** PDF export fonts were
  inlined as base64 and made up three quarters of the package; they, the math
  fonts and stylesheet, the pdf.js worker, and Tree-sitter grammars now load
  from `https://revise.io` when first needed. **`setAssetBaseUrl(url)`**
  points the SDK at a self-hosted mirror.
* **`import ReviseEditor from "revise/editor"`.** The editor entry now has a
  default export. The named `ReviseEditor` export still works.
* **`revise` root entry** with `REVISE_SDK_VERSION`, `REVISE_SDK_BUILD`, and
  the shared types, and no runtime weight.
* **`THIRD-PARTY-NOTICES.md`** lists every bundled open-source package with
  its license.
* **Anonymous usage ping, and the `telemetry` prop to turn it off.** Once
  per page load, the editor sends Revise its version; the browser adds the
  site's origin. Development hosts are counted per day and version without
  their origin. No cookies, user data, or document content.
  `telemetry={false}` disables it.

### Fixed

* **Math renders with its real fonts in host apps.** Equations looked for
  their fonts and stylesheet at the host's own `/fonts` and `/katex.min.css`
  and fell back to system fonts; the help link in the editor menu also
  pointed at the host's `/help`. All now resolve to Revise's assets.
* **The SDK no longer reaches for development servers.** Revise application
  endpoints (document history, preferences, uploads, failure reports) and the
  sync-server addresses no longer resolve to `localhost` in an embedding
  host. Document history in particular fetched from `localhost:3001` in
  browsers without a `process` global.
* **No debug globals on the host's `window`.** `__getEditor`,
  `__getDocLayout`, and `__aiLogs` are no longer installed.
* **DOCX math export uses Revise's own MathML → OMML converter.** Equations
  export to native Word math (fractions, radicals, scripts, sums and
  integrals with limits, delimiters, matrices, accents, bars, braces,
  functions, boxed and text runs) with no third-party copyleft code in the
  package. Re-importing them is more faithful: `\left\{ … \right.`,
  `\underline`, `\overbrace`, `\boxed`, `\text{…}`, `\mathbb`, binomials,
  and named functions (`\sin`, `\log`, `\lim_{…}`) now come back as the
  same LaTeX instead of approximations, and symbols no longer run into the
  following letter (`\alpha x`, not `\alphax`).

## 2.0.0-alpha.7

### Fixed

* **DOCX round trips keep every modeled mark and block.** A new
  export → import matrix (every formatting mark in every text context,
  every paragraph, list, table, cell, image, code, math, note, header,
  footer, and page-layout attribute, plus a second-pass fixed-point
  check) found and pinned a set of losses: lists inside table cells
  were dropped on export; hanging indents exported as zero and
  `w:hanging` was ignored on import; headings came back as Word's blue
  16pt built-ins (export now writes the editor's heading sizes with
  inherited color); unscoped header/footer blocks were not exported;
  hyperlinks discarded an explicit text color; links inside footnotes
  were lost on import; header and footer runs used a reduced codec in
  both directions and now share the body run codec, links and inline
  code included; inline code and code blocks flattened to Courier text
  and now travel as `CodeInline` / `CodeBlock_<language>` styles and
  return as the original nodes; todo items exported as literal
  `[x]` text and now use checkbox glyphs that re-import as todo lists
  with their checked state; code-block line breaks doubled on
  re-import; and a single run in another font restamped the whole
  document (the inferred document font is now the character-weighted
  majority).
* **Table borders export and re-import faithfully.** Export no longer
  throws on non-hex colors such as `TRANSPARENT`, `rgba()`, or CSS
  names — unresolvable values are omitted or written as `auto`. The
  uniform `borderWidth`/`borderColor` pair is honored (width 0 means
  no borders), width-0 spec edges export as `none` instead of a
  hairline, and an explicit `w:sz="0"` imports as hidden rather than a
  1px line. Table Settings border changes now rewrite the structured
  table spec and clear per-cell overrides, so hiding borders on an
  imported table takes effect.
* **Byte-preserving DOCX export degrades instead of failing.** A carrier
  that fails to load falls back to the regenerated package like every
  other graft failure; the graft option reports its outcome (exact,
  grafted, regenerated, and the fallback code) through an isolated
  callback that can never break an export. Untouched imports of rich
  documents now export byte-identical: note-body font inheritance,
  header/footer zone ids, and legacy chrome no longer drift the
  fidelity signatures; watermark and settings edits graft instead of
  restoring carrier values; body grafting is invalidated when wrapper
  or style sidecars change; single-quoted and non-numeric relationship
  ids parse; and a changed header image is replaced even when its
  media filename collides.
* **Formatting suggestions preserve footnotes.** Accepting a
  `style_blocks` suggestion keeps footnote references and bodies.
* **Large documents no longer stall on batch edits.** Styling 205 blocks
  in a 10,000-block document, applying 100 replacements, and large
  multi-block insertions run without re-decoding the document per
  action; suggestion projection latency is bounded; batch paragraph
  formatting suggestions behave identically through preview,
  acceptance, and rejection.
* **Semantic tool errors and inputs.** Errors distinguish Markdown find
  syntax from stored plain text; metric CSS paragraph indentation
  (`cm`, `mm`) is accepted; number-dot prose can be parsed as inline
  text instead of a list when requested.
* **Comments render AI citations.** Structured citations persist on
  replies and render in the panel; unsupported provider citation
  markers are hidden, including on legacy comments.
* **Agent image rehosting.** Wikimedia thumbnail URLs are recovered by
  rehosting the original image, and rate-limited rehosts surface the
  backend reason and status.
* **Revision timeline never collapses to zero.** A stale or missing
  server update counter no longer disables history or pins every frame
  to the first update; loaded frames are authoritative.
* **Pasted images write once.** A pasted image no longer inserts a
  temporary base64 placeholder that is replaced later; the final hosted
  URL is written at the captured paste position when the upload
  completes.

### Changed

* **Comment margin geometry is direction-aware.** Chip, floating-stack,
  and insert-chip positions are computed along an outward axis with a
  single conversion to physical coordinates. The embedded document
  surface itself is still laid out left-to-right: the margin chrome
  stays on the page's right regardless of the host page's direction.
  Mirroring the embed for right-to-left hosts is not part of this
  release.

## 2.0.0-alpha.6

### Fixed

* **A healed seed race now recovers full fidelity — and never loses a
  comment.** Three repair refinements: the winner is the seed whose
  metadata survived the merge (each seed stamps a ballot in the same
  transaction), so the kept content matches the surviving import
  capture; a shared deterministic id keeps the WINNER's element, not an
  arbitrary one; and map records under a shared key (deterministic
  comment ids) are never deleted — the merge already deduplicated them,
  and alpha.5's repair removed the only surviving record. A raced,
  repaired room now reports "exact" and exports byte-identically.

## 2.0.0-alpha.5

### Fixed

* **Seed-race repair kept a duplicate footnote.** Deterministic ids that
  every seed generates identically (docx footnotes) were protected from
  repair as a collision safeguard, leaving one copy per seed. Repair now
  keeps exactly one occurrence of a shared id. Supersedes 2.0.0-alpha.4,
  which was deprecated minutes after publish.

## 2.0.0-alpha.4

### Fixed

* **Double-seed connect race no longer duplicates the document.** Two
  peers that each found an empty room and seeded the same file before
  syncing used to merge into a perfectly-synced, perfectly-duplicated
  document. Every seed now records a claim in the same transaction as
  its content, and any peer that sees two claims deterministically
  removes the losing seed's content — idempotent, convergent, and
  content added after a seed is never touched. `seedYDocFromFile` is
  now genuinely safe to call on every connection: a later call also
  heals an already-raced room, and every live editor session repairs
  one the moment the second claim syncs in.
* **Editing no longer rewrites document properties.** A structural edit
  (or a rejected tracked change) permanently dropped the imported core
  properties from the live model, so every later export regenerated
  `docProps/core.xml` with an "Un-named" creator, the title removed,
  and the creation date reset to export time. Core properties now
  survive every model rebuild, and when core.xml IS legitimately
  regenerated it is a faithful merge: `cp:revision` round-trips and
  fields the original never had are not invented.
* **`docProps/app.xml` passes through untouched.** It is never
  regenerated (preserving Application/Company/TotalTime) and never
  added to a package that did not have one.

### Added

* **`repairSeedRace(ydoc)`** on the backend entry (with
  `SeedRaceRepairResult`): detect and repair a double-seed race on
  demand. Editor sessions and `seedYDocFromFile` run it for you.

### Changed

* **New reserved top-level key in shared documents: `"seed-claims"`**
  (see `RESERVED_DOCUMENT_KEYS`) — where seed claims live.

## 2.0.0-alpha.3

### Fixed

* **Backspace before a chip deleted the chip.** A preserved-object chip
  has two caret stops — before and after — and a delete now respects
  which side the caret is on, like a caret between two characters:
  backspace at the before-stop targets the block BEFORE the chip (an
  atomic neighbor is deleted whole, a text neighbor loses its last
  character), and forward delete at the after-stop targets the block
  after. Deletes pointing AT the chip still remove it.
* **Up/down arrows at a chip slid the caret to the chip's other side**
  instead of changing lines. Vertical movement now leaves the chip's
  line and lands on the neighboring block's stop nearest the caret's
  column — arrowing through a stack of chips keeps the caret on the
  same side all the way down.

## 2.0.0-alpha.2

### Fixed

* **Exporting .docx could crash in production builds of the host app**
  ("Cannot destructure property 'default' … as it is undefined" from
  the converter's zip loader). The SDK's build emitted duplicate
  interop chunks for its zip dependency behind dynamic imports, and
  some consumer bundlers resolved one family to `undefined` when
  producing production builds — development builds were unaffected,
  which is why the crash only appeared after deployment. The dependency
  is now a static import inside the (still lazily loaded) converter
  modules: the load profile is unchanged and the chunk graph no longer
  depends on the host bundler's interop handling.
* **Backspace in an empty paragraph directly after a chip deleted the
  chip** instead of the paragraph. Preserved payloads are content the
  source file owns, not editor furniture: the empty paragraph dies, the
  chip survives. (Page and section breaks keep their old
  consume-on-backspace behavior.)
* **Chips gained real before/after caret stops.** The caret can now be
  placed on either side of a chip — arrow keys walk across it, and
  clicking the left or right half of the chip places the caret on the
  matching side.

## 2.0.0-alpha.1

Prerelease for evaluation. The 2.0 line's headline is DOCX source
fidelity: a document imported from .docx can now leave the editor as the
file it came from, not a reconstruction of it.

### Added

* **DOCX source-fidelity mode (default on).** Importing a .docx keeps the
  original package inside the document (the "carrier", shared documents
  included, capped at 25MB). On export, content you did not touch is
  emitted as the exact bytes that arrived — byte-for-byte, unannotated —
  and only changed content is regenerated. A verification stage inspects
  every composed package and falls back to full regeneration rather than
  ship anything it cannot verify.
* **`handle.getSourceFidelity()`** (and `ydocSourceFidelity(ydoc)` /
  `documentToDocx(doc, { originalDocx })` on the backend entry) reports
  the honest relationship of the next export to the original file:
  `"exact"` (byte-identical), `"grafted"` (original bytes plus your
  edits), or `"converted"` (no usable original; the report says why).
* **Unmodeled Word formatting survives editing.** Run, paragraph, table,
  row, cell, and section properties the editor does not model (vendor
  effects such as `w14:glow`, revision-save ids, row heights, table
  look flags, page borders, note-numbering properties…) are carried
  through the model and re-emitted — so an EDITED paragraph keeps them
  too, with or without the carrier.
* **Preserved objects render as labeled chips.** OLE embeds (Excel,
  Visio), SmartArt without a raster fallback, and unknown OOXML
  constructs import as atomic blocks labeled with their source tag
  (e.g. "w:object · Excel.Sheet.12"), render as chips on canvas and in
  PDF export, and re-export verbatim. In agent HTML they appear as
  `<docx-raw id tag/>`: an agent can keep, move, or omit one
  (omission deletes), but can never inject raw OOXML of its own.
* **Editable-region permissions preserved.** `w:permStart`/`w:permEnd`
  pairs (and future paired ranges) survive import, editing, and export
  with balance guaranteed by construction: typing inside extends the
  region, deleting its text retires it, and unbalanced pairs in source
  files are repaired at import.

### Changed

* **BREAKING: two new reserved top-level keys in shared documents** —
  `"docx-carrier"` and `"oxml-ranges"` (see
  `RESERVED_DOCUMENT_KEYS`). A host-built Y.Doc already using these
  names is rejected by `assertUsableSharedDocument`.
* **BREAKING: docx-sourced exports are byte-preserving by default.**
  1.x regenerated every export from the model; 2.0 reproduces original
  bytes for untouched content. Hosts that depended on exports being
  normalized into the generated dialect should convert explicitly.
* `ReviseDocument` block children may now include the `"docx-raw"`
  node type (opaque; convert rather than inspect, as ever).
* Shared documents built from a .docx are larger by roughly the size of
  the source file (the carrier). It is stored once, chunked, and synced
  like any other document state.

## 1.3.1

### Fixed

* **Delegated page inspection now reaches the embedded editor canvas.** The
  SDK connects the delegated agent's `render_document_pages` tool to the
  mounted document renderer, so appearance and layout requests return the
  actual pages instead of reporting that canvas inspection is unavailable.
* **Agent-tool documentation now matches the generated SDK catalog.** The
  public docs use the canonical `remove_blocks` name, distinguish the
  deterministic document-local tool subset from delegated-agent-only tools,
  and explain where visual page inspection is available.

## 1.3.0

### Added

* **The built-in editor UI now localizes itself in English, Spanish, and
  German.** Ribbon controls, menus, dialogs, comments, Review mode, and agent
  chrome follow the browser language or the persisted Revise UI-language
  preference, while English remains the fallback if a locale chunk cannot be
  loaded.
* **The delegated browser agent can inspect the document's rendered pages.**
  It can request bounded appearance contact sheets or layout diagnostics from
  the real canvas renderer, including page geometry, tables, images, math,
  headers, footers, and safe placeholders for unavailable visual assets.

### Changed

* **Tab editing and layout now follow Word-style paragraph behavior.** Tab and
  Shift+Tab at the start of a block keep indenting or outdenting, while either
  key inside paragraph text inserts a tab. Long tabbed lines wrap at word
  boundaries, restart their ruler on each visual line, and preserve custom,
  aligned, leader, and right-to-left tab stops.

### Fixed

* **DOCX named styles remain stable through editing and repeated round trips.**
  Imported paragraph styles and document defaults now drive newly created
  headings and agent-created styled blocks, survive Yjs persistence, suppress
  redundant direct formatting on export, and converge without accumulating
  unused generated Word styles. Explicit formatting resets, borders, spacing,
  fonts, and styles inside table cells remain intact.
* **Agent document measurements reconcile pending Review changes.** Primary
  totals consistently measure the final, as-if-accepted document and include
  the original review projection when pending suggestions make the visible
  word or character count differ.

## 1.2.0

### Added

* **International text support now extends across the editing and conversion
  pipeline.** Unicode-aware line breaking, search, list numbering, font
  fallback, and IME composition preserve multilingual text more reliably, and
  text import now detects UTF-8 and UTF-16 files. HTML, DOCX, RTF, ODT, and
  plain-text conversions keep the expanded script coverage intact.
* **Orange and purple join the SDK highlight palette.** The editor UI,
  `find_highlights`, `style_blocks`, agent HTML, and DOCX round trips now
  share the same seven canonical highlight colors.
* **Agent styling covers richer document structures.** `style_blocks` adds
  span, descendant-wildcard, first-row, and named-paragraph-style selectors,
  with durable mappings for image sizing and alignment, paragraph borders,
  nested tables and lists, per-edge cell borders, cell fills, padding, and
  table-cell text styles.

### Fixed

* **DOCX import follows Word's effective paragraph and table styling.**
  Unstyled paragraphs inherit the document's default style; exact and
  at-least line rules use the resolved font size; paragraph before/after and
  contextual spacing replace the editor's fallback gap; missing table borders
  remain borderless; and non-uniform cell margins survive import. The imported
  spacing persists through Yjs, paragraph splits and merges, HTML, DOCX, and
  PDF output, keeping compact Word layouts from growing onto extra pages.
* **Unavailable Word fonts use the document's own substitution hints.** DOCX
  import reads `fontTable.xml` alternate names and PANOSE/family/pitch
  metadata, persists them with the document, and chooses metric-compatible
  fallbacks before resorting to a generic family.
* **Multilingual PDF export embeds and shapes the scripts it needs.** Chinese,
  Japanese, Korean, Indic, Southeast Asian, Tibetan, Ethiopic, Armenian,
  Georgian, Syriac, Thaana, symbols, emoji, and rare Han use bundled lazy
  fallback faces, while a hidden logical-text layer preserves search and text
  extraction.
* **Agent edits preserve complex formatting and pending review state.** Styled
  tables, nested content, list-item formatting, explicit text overrides,
  comments, and edits layered over pending insertions now survive preview,
  acceptance, and rejection without duplicating or flattening structure.
* **Borderless layout tables stay visually borderless while editing.** The
  canvas now reveals only the specific invisible vertical edge under a resize
  pointer instead of ghosting the table's entire grid on hover or focus.
* **Imported pale-yellow highlights remain highlights.** HTML clipboard import
  no longer remaps Word's pale yellow to the editor's green palette entry.

## 1.1.0

### Added

* **First-class right-to-left editing.** The built-in toolbar can set paragraph
  and list direction to automatic, LTR, or RTL. Mixed Hebrew, Arabic, and
  left-to-right text now uses bidi-aware line layout, visual arrow-key
  movement, stable caret and selection geometry, direction-aware alignment and
  indents, mirrored list markers, and RTL tab stops. Direction survives Yjs,
  clipboard and agent edits, HTML, and DOCX round trips; PDF export preserves
  mixed-direction reading order and positioning.
* **Multi-column sections.** Page layout now supports one, two, or three
  newspaper-style columns with a configurable gap. Continuous section breaks
  balance their final columns, while page and next-page sections keep ordinary
  pagination. The canvas editor and PDF export share the flow rules, DOCX and
  HTML import/export preserve the settings, and `set_page_layout` exposes
  `columnCount`, `columnGap`, and section-scoped updates to browser and
  server agent sessions.
* **Native document-structure tools.** `insert_block` can create a live table
  of contents with `<toc levels="3"></toc>`. The canonical
  `remove_blocks` tool can delete a counted range, exact IDs, a saved search
  result, or an explicitly authorized document tail with `through_end`.

### Changed

* **Agent tool sessions avoid unproductive read cycles.** Sequential reads now
  reject windows containing only blocks already returned in the same request
  with `no_new_read_context`; `read_specific_blocks` remains available for
  intentional revisits. `remove_blocks` is now the model-facing name, while
  the previous `remove_block` name remains an executable compatibility alias.

### Fixed

* **Strict-provider nulls behave like omitted optional tool fields.** Browser
  and server tool execution normalize provider-materialized `null` values
  from the generated schema before dispatch, without stripping required or
  deliberately nullable values. Optional layout and mutation inputs therefore
  no longer take invalid branches merely because a provider filled them in.
* **Agent-generated Unicode escapes become the intended text.** Literal
  `\uXXXX` sequences in agent HTML and replacement paths are decoded without
  disturbing escaped backslashes or code spans, preventing visible escape text
  in edited documents.
* **Review decisions preserve the reader's place.** Accepting or rejecting a
  tracked change no longer forces the embedded editor to scroll back to the
  active suggestion.
* **SDK PDF export keeps Hebrew and Arabic text self-contained.** The package
  now bundles the Noto fallback faces used by RTL export, so embedding hosts do
  not need to mirror Revise's public font directory to avoid dropped glyphs.

## 1.0.1

### Fixed

* **Malformed model input can no longer crash a host's agent loop.** A bare
  string where `search_document` expects a `queries` array — the most
  common model slip — threw a raw `TypeError` out of `execute()` /
  `executeDynamic()` instead of returning a structured failure. Bare
  strings are now coerced to one-element arrays (also for
  `read_specific_blocks`' `block_ids`), anything uncoercible fails
  structurally, and both surfaces gained a safety net that converts an
  unexpected handler throw into an `internal_error` result. The documented
  contract — expected failures as results, only environment errors reject —
  now holds for arbitrary input.
* **Invalid enum values no longer mutate the wrong target silently.** An
  insert tool called with `position: "above"` placed content *after* the
  reference block while reporting success, and `set_header_footer` with a
  misspelled or missing `side` edited the header. Both now return a
  structured failure naming the valid values.

## 1.0.0

One package, one tool contract. The browser and server surfaces now speak
the same canonical envelope, so host result-handling code is shared verbatim
between web and Node. That convergence is breaking on the browser side —
every change is listed below.

### Breaking

* **`tools.execute()` returns the canonical discriminated envelope.** The
  flat `{ toolCallId, name, success, error?, agentFeedback?, output?,
  documentContent? }` result is gone. Both surfaces now return
  `{ ok: true, value: { callId, tool, message, data, context, suggestionIds } }`
  or `{ ok: false, error: { callId, tool, code, message } }`
  (`ReviseToolResult`). Field mapping: `toolCallId → value.callId`,
  `name → value.tool`, `agentFeedback → value.message`,
  `output → value.data`, `documentContent → value.context.html`;
  `view_image`'s attachment lives on `value.image`.
  `ReviseEditorToolExecutionResult` no longer exists.
* **`tools.execute()` is typed and no longer routes `document_id`.**
  `execute()`/`call()` take the generated per-tool input types and
  cover the shared 24-tool contract; untrusted model calls — including the
  browser-only `get_selection`, `view_image`, and
  `revise_run_agent`, and model-facing `document_id` routing — go
  through the new `executeDynamic()`, exactly as on the server.
* **Unknown tools and role denials are results, not throws.** `execute()`
  returns `{ ok: false }` with `code: "unknown_tool"` or
  `"role_not_permitted"` instead of throwing; the new `tools.call()`
  throws a typed `ReviseToolError` for hosts that prefer exceptions.
  `ReviseRoleError` is still thrown by `agent.run()` and UI
  controllers.
* **ID-keyed suggestion decisions return per-ID outcomes.**
  `review.acceptSuggestions`/`rejectSuggestions`,
  `review.acceptCommentSuggestions`/`rejectCommentSuggestions`, and
  `tools.acceptAllSuggestions`/`rejectAllSuggestions`, and the server
  session's `acceptSuggestions`/`rejectSuggestions` return
  `{ resolved, missing, unresolved }` (`ReviseSuggestionDecision`)
  instead of a bare count. Stale IDs land in `missing`; a role that may
  not resolve reports everything `unresolved`. `review.acceptAll()` /
  `rejectAll()` keep their boolean UI-gesture contract.
* **Server sessions default to suggesting mode.** `createServerDocumentSession`
  without `mode` now proposes tracked changes instead of applying edits
  directly — the same default posture as the browser surface, and the safe
  one. Pass `mode: "editing"` (or per-call `directMode: true`) for
  direct application.

### Added

* **Browser mutation results report created suggestion IDs.** Successful
  mutations carry `suggestionIds` — the tracked records that call created
  (empty for direct edits, `null` for read/search/measure tools) — with a
  concurrent human suggestion never attributed to the tool call. Feed them
  straight to `review.acceptSuggestions()`.

* **The tool contract types ship from both entries.** `ReviseToolResult`,
  `ReviseToolResponse`, `ReviseToolFailure`, `ReviseToolError`,
  `ReviseSuggestionDecision`, the generated `ReviseToolInputMap`, and
  friends are exported by `@reviseio/sdk` and `@reviseio/sdk/backend`
  alike.

* **Server mutation results report the tracked records they created.**
  Successful mutation calls from `createServerDocumentSession` now carry
  `suggestionIds` — the tracked suggestion records that call created (empty
  for direct edits, `null` for read/search/measure tools) — so a host can
  persist per-edit IDs with its review workflow instead of diffing the
  document-global pending set.

* **`listSuggestions()`** returns every pending suggestion as a reviewable
  record with authorship metadata (`authorType`, `agentName`,
  `agentModel`, `source`, `label`, `createdAt`), so hosts can decide on
  their own agent's suggestions and leave collaborators' pending work alone.

* **`acceptAllSuggestions()` / `rejectAllSuggestions()`** make the
  whole-document decision an explicit, greppable call instead of the
  `acceptSuggestions(getPendingSuggestionIds())` idiom.

### Fixed

* **Server tool types now resolve for `moduleResolution: "NodeNext"`
  consumers.** The packaged declarations re-exported the server tool contract
  through extensionless relative specifiers, which NodeNext cannot resolve —
  every tool input/output type silently degraded to `any`, and importing a
  contract type by name (e.g. `ServerDocumentSession`) failed to compile.
  The declarations now use explicit `.js` specifiers, which every supported
  resolution mode maps to the sibling `.d.ts` files.
* **Importing a document with code blocks no longer risks crashing a Node
  host.** The canvas syntax highlighter tried to fetch its tree-sitter wasm
  under Node (the server DOM shims install a jsdom `window`, defeating its
  browser check), failing as an unhandled promise rejection. Highlighting now
  recognizes the server runtime explicitly and stays off, and a failed
  highlighter init in the browser no longer poisons later attempts.
* **Table and list mutations no longer spam `Invalid access` warnings.**
  Building table rows, cells, and list items called Yjs `push()` on
  elements not yet integrated into a document, which logs a warning per
  child. Construction now inserts children at explicit indices — dozens of
  stderr lines per table insert in server logs, gone.
* **Editing mode applies server edits directly again.** A server session in
  `"editing"` mode quietly recorded every mutation as a
  pending tracked suggestion instead of applying it. Editing-mode calls now
  run in the runtime's direct mode and settle within the call, matching the
  documented behavior; an explicit per-call `directMode` still overrides in
  either direction.

## 0.9.0

### Added

* **`review.listChanges()` now reports linked moves as moves.** A move pair
  surfaces as ONE `ReviseTrackedChange` with `kind: "move"`,
  `moveSourceBlockIds`/`moveDestinationBlockIds` locating each half, and
  `deletedText`/`insertedText` carrying the text as it left and as it
  arrived. Previously both halves were folded into a single change labeled
  `"delete"`, leaving a host review panel no way to distinguish a move from
  a replacement. Accept/reject semantics are unchanged: resolving the change
  settles both locations atomically.

## 0.8.0

### Added

* **Cut and paste now creates native linked moves in Suggesting mode.** Cutting
  text from supported paragraphs and pasting that same internal clipboard
  payload elsewhere in the document produces one atomic “Moved from”/“Moved
  here” pair. Accepting or rejecting either half resolves both locations, undo
  cannot strand an orphaned half, and DOCX export/reimport preserves native
  linked move markup. Copy/paste, editing mode, reused or mismatched clipboard
  payloads, and unsupported structural selections continue to use ordinary
  insertion/deletion behavior.

## 0.7.0

### Added

* **Server-side semantic tools.** `await createServerDocumentSession(ydoc, { documentId, mode })` in `@reviseio/sdk/backend` binds the canonical
  document-local agent tools — read, search, measure, mutate, layout,
  footnotes, tables, comments — to a host-owned Y.Doc under plain Node.
  `mode: "suggesting"` produces Word-compatible tracked changes with
  accept/reject; concurrent calls are serialized; literal tool calls infer
  their schema inputs and structured outputs. See the README's "Server semantic
  tools" section.
* **Linked Word moves now round-trip as atomic move suggestions.** DOCX import
  pairs native `w:moveFrom` and `w:moveTo` ranges across runs, paragraphs,
  and table cells. Accepting either half keeps the text at its
  destination; rejecting either half restores its original location; export
  re-emits native paired move markup. Suggestion cards distinguish “Moved from”
  and “Moved here”, and focusing either half highlights its partner even across
  paragraphs.

### Fixed

* **Node-side DOCX imports preserve tracked table-row revisions without a
  browser `FileReader`.** The backend DOM shims and table-revision
  postprocessor now work from `Blob.arrayBuffer()`, retaining row insertion
  and deletion metadata in server integrations.
* **Word comment anchors preserve their identity and semantic range.** Safe
  native numeric IDs no longer shift, cross-paragraph and table-cell ranges
  emit one anchor triple instead of duplicates, and collapsed, overlapping,
  threaded, and resolved comments survive repeated round trips.
* **Visible drawing text survives DOCX import when shape geometry is
  flattened.** Inline and anchored DrawingML, grouped shapes, legacy VML,
  headers, and standards-valid `mc:AlternateContent` Choice/Fallback content
  become editable paragraphs in reading order without duplicate fallback text.
* **DOCX archives no longer inflate and large imports avoid repeated work.**
  Generated packages use DEFLATE compression, parse the main document XML once,
  and skip move indexing when a file has no moves, preventing the reported
  multi-fold output growth and superlinear no-move scan.

## 0.6.0

### Added

* **Horizontal rules and ornamental dividers are now supported throughout the
  editor.** Insert thin, thick, double, dashed, dotted, star, or diamond
  dividers from the toolbar or context menu, or create them with text triggers
  such as `---`, `===`, `-**-`, and `-<>-`. DOCX, HTML, Markdown, agent HTML,
  PDF, and plain-text output preserve the divider where the format permits;
  DOCX, HTML, Markdown, RTF, and ODT imports recognize their native divider or
  paragraph-border representations.

### Changed

* **Em-dash autocorrection now waits for a word boundary.** Typing `--` remains
  literal until Space or Enter, allowing `---` to be used for horizontal-rule
  insertion and preserving word-initial values such as `--flag`.

### Fixed

* **Words no longer wrap in the middle at formatting or tracked-change run
  boundaries.** A word split across differently styled text nodes now wraps as
  one unit and keeps a stable layout when suggestions are accepted.
* **Suggestion editing produces stable runs and caret placement.** Continued
  typing or backspacing merges into the existing suggestion instead of creating
  one run per keystroke, replacement normalization no longer leaves the caret
  inside hidden deleted text, and Enter after a pending deletion creates the
  expected paragraph or list item without moving the deleted content.
* **Structural editing keeps the expected document shape and keyboard focus.**
  Backspace exits or splits empty list items correctly, compatible lists rejoin
  when their separating empty paragraph is removed, Enter at the start of a
  leading heading or code block creates a body paragraph above it, and toolbar
  commands no longer steal keyboard focus from the editor.

## 0.5.1

### Fixed

* **PDF table-of-contents page numbers stay accurate when a heading moves to
  the next page.** Export now records a heading's destination after paragraph
  pagination, so a keep-with-next or end-of-page preflight cannot leave the
  TOC pointing at the page the heading would have occupied before it moved.

## 0.5.0

### Added

* **Comments now work on list items, including nested items.** Selecting list
  text, expanding a word from the caret, and commenting on a whole item all
  create item-local anchors. Returning the caret to that text activates the
  thread, list-item threads survive agent-HTML round trips, and the
  `leave_comment` agent tool accepts list-item IDs.

### Changed

* **PDF export now follows the editor's layout and print semantics much more
  closely.** It shares wrapping and pagination rules for tab stops and
  leaders, hyphenation, keep-with-next, keep-lines, widows and orphans, code
  blocks, nested tables, footnotes, page and section breaks, live TOC page
  numbers, line numbers, and watermarks. Editor-only placeholders and review
  chrome are not printed, and Word hidden text remains hidden in ordinary PDF
  output. The SDK now carries its metric-compatible PDF fonts itself, so an
  embedding host does not need to mirror Revise's public font directory.
* **Agent tool sessions reject redundant full-document read loops.** After a
  session has read the complete document, another sequential `read_document`
  returns `no_new_read_context`; agents can still revisit known content with
  `read_specific_blocks`.

### Fixed

* **DOCX formatting exceptions survive a complete edit and export cycle.**
  Explicit run-property clears over named styles, zero paragraph indents,
  paragraph border and shading clears, decimal font sizes, and mixed small-cap
  and all-cap overrides now remain distinct from inherited formatting and do
  not leak into adjacent text.
* **Complex Word structures no longer lose modeled content on re-export.**
  Internal bookmark links stay internal; exact table widths, columns,
  alignment, cell padding, and vertical alignment survive; nested tables keep
  the paragraphs around them; display equations are not flattened when a file
  is immediately re-exported; and multi-block footnotes and endnotes can retain
  their lists and tables.
* **Accepting or rejecting a compound agent edit is atomic.** Mixed text,
  formatting, and structural suggestions are resolved together, so accepting
  a rewrite no longer retains deleted fragments and rejecting it restores the
  original content and formatting.
* **Comment cards stay where users put them.** A previously active card no
  longer drifts with the viewport, and selecting text inside a card no longer
  jumps focus back to the document or clears the selection. Inline code in
  comment bodies is also styled as code.
* **Package managers can no longer omit the Yjs runtime.** Every editor session
  is Yjs-backed even without a collaboration provider, so `yjs` and
  `y-protocols` are now required peers instead of optional peers. This makes
  package managers install or validate them instead of letting bundlers
  substitute empty optional-peer modules and fail the consumer build.

## 0.4.5

### Fixed

* **Starting a list no longer drops the font.** Typing a list trigger
  (`- `, `1. `, `[] `) in a paragraph set in a non-default font produced
  a list item that fell back to the default font: clearing the trigger text
  left an empty item with nowhere to carry its formatting. The formatting at
  the trigger's trailing edge — the font family included — is now preserved
  on the empty item and applies to the next character typed.

## 0.4.4

### Fixed

* **Suggestion cards now hang from the suggested text.** The floating
  accept/reject card anchored to the caret; it now follows the suggested
  fragment (or your selection) and sits centered below its line, the same
  placement the revise.io app uses, falling back to the caret only when the
  fragment cannot be measured. Wide cards are clamped to the page edges
  instead of a fixed margin.

## 0.4.3

Identical in content to 0.4.2; republished.

## 0.4.2

### Fixed

* **Word-level diffs misplaced edits next to repeated words.** When the text
  adjacent to an edit repeated a word from the edit itself (replacing
  "\[Berkshire County / appropriate Massachusetts county]," with "Suffolk
  County, Massachusetts," just before "Massachusetts will"), the unchanged
  suffix could be drawn as deleted and retyped. Unchanged repeated words now
  stay anchored as unchanged, in tracked changes and the diff view alike.
* **Writing a comment no longer collapses the comments margin.** Finishing a
  draft that had itself opened the margin always collapsed it — even when
  submitting had just created a thread, so the pages jerked sideways in both
  directions and hid the card the user just wrote. The margin now stays open
  on the new thread; only an abandoned draft with no other open thread
  collapses it.
* **Comment card placement around drafts and tracked changes.** A comment
  draft started while hovering the card stack could pin its card — and drag
  the viewport — to the top of page 1; it now anchors where the draft was
  made. A caret inside a resolved thread's highlight, or inside an imported
  thread's replies, activated no card at all; it now activates the right
  open thread. And when a commented paragraph also contains tracked changes,
  the card describes the change under the cursor instead of jumping to the
  top of the paragraph.
* **The selection card no longer chases the pointer mid-drag.** While the
  mouse button is down nothing pops up under the pointer; the card appears
  on release, anchored below the selection the user meant.

## 0.4.1

### Fixed

* **Opening the export menu crashed.** An icon component in the export menu
  referenced React without importing it, which the packaged build has no
  global to fall back on.

## 0.4.0

### Changed

* **The default entry no longer ships Tree-sitter syntax highlighting or the
  embedded WASM payload.** Code blocks still render as code, and every WASM
  hot path has a TypeScript implementation. This keeps the normal
  integration smaller and compatible with strict Content Security Policies.
  Optional features now load as async chunks inside the package.

### Added

* **`@reviseio/sdk/full`** — an opt-in entry point that keeps token-colored
  code blocks and the WASM hot paths. The API and stylesheet are identical
  between the two entries.

## 0.3.4

### Fixed

* **The SDK no longer attempts any telemetry.** Earlier builds emitted
  editor health metrics toward a Revise backend that does not exist in your
  deployment, which could only fail — loudly, as console CORS errors — and
  represented network calls you never asked for. Telemetry is now something
  only the revise.io application itself can switch on; embedded editors
  send nothing anywhere: no metric POSTs, no analytics vendor code, no
  beacons.

### Added

* **`onAnalyticsEvent`** — the editor's own instrumentation, delivered to
  the host instead:
  `<ReviseEditor onAnalyticsEvent={(event, properties) => ...} />`.
  Forward events to your own analytics service; a throwing handler never
  breaks the editor. Event names and property shapes are internal and
  version-unstable.

## 0.3.3

Four suggesting-mode fixes, two of them content corruption. If your users
edit in `suggesting` mode — the mode this SDK exists for — take this
release.

### Fixed

* **Pasting in suggesting mode corrupted the document.** The paste path
  predated suggesting mode: it duplicated the rest of the paragraph and
  inserted the pasted text without tracked-change marks, so the paste was
  invisible to review and survived reject. Pasting is now recorded exactly
  as if the pasted characters had been typed — an insertion suggestion, plus
  a deletion suggestion for any replaced selection.
* **Formatting across a pending change destroyed it.** Applying bold (or any
  inline format) over a range touching a pending insertion or deletion
  overwrote the change's identity; resolving the format then silently turned
  a pending insertion into accepted text, or resurrected deleted text.
  Formatting now leaves deletion spans alone, folds into insertion spans (as
  Word nests run properties inside `w:ins`), and records a reviewable
  format change only on unmarked text.
* **Accepting a deletion that crossed a paragraph boundary left the
  paragraphs unmerged.** The boundary is now part of the suggestion, as the
  pilcrow is in Word: accepting merges the paragraphs, in any resolution
  order, for any number of paragraphs in the selection.
* **Copying a selection inside your own pending insertion copied nothing.**
  It now copies the selected text. Clipboard payloads are also sanitized so
  tracked-change marks never travel with copied content.

### Console

* Opening a document no longer logs to the console (previously one Yjs
  warning per block plus two internal debug lines). `console.warn` and
  `console.error` remain for genuinely actionable problems.

## 0.3.2

### Fixed

* `editor.whenReady()` was missing from the published type declarations. It
  worked at runtime, but TypeScript rejected the call the documentation tells
  you to make.

## 0.3.1

### Fixed

* Using the editor handle from `onReady` no longer throws. `onReady` fires
  before any document exists, and "subscribe to everything on ready" is the
  first thing a host writes — a subscription placed then now waits and
  attaches when a document arrives. `selection.observe()` was affected too.
  Methods that act on a document still fail loudly, and the message now names
  the fix.

### Added

* `editor.whenReady()` — resolves once a document is open and its
  controllers are usable.
* `REVISE_SDK_VERSION` and `REVISE_SDK_BUILD` exports, and a `bugs` entry
  in the manifest: a support ticket can name the exact build it came from.

## 0.3.0

### Collaboration

Multi-user editing over a Yjs transport you own. The editor builds the
document; you attach the connection:

```ts theme={null}
collaboration: {
  connect: (doc, awareness) =>
    new HocuspocusProvider({ url, name, document: doc, awareness }),
  synced,
}
```

Remote carets, a presence roster (`editor.collaboration`), seed-or-join
semantics, and validation of any document you supply. See the collaboration
guide.

### Roles

`role="editor" | "suggester" | "viewer"`, editor-wide or per document, and
enforced on every surface: typing, the built-in chrome, the handle, and agent
tool calls. A suggester cannot leave suggesting mode, apply anything directly,
or accept and reject.

### Tracked changes you can list

`review.listChanges()` and `review.getChange(id)` return each pending change
with its kind, author, timestamp, affected blocks, and text — enough to build
your own review panel. Imported Word redlines keep their original reviewers.

### Server-side primitives

New subpath export `@reviseio/sdk/backend` (Node only): `parseDocument`,
`fileToYDoc`, `seedYDocFromFile`, `ydocToDocx`, `encodeYDoc`/`decodeYDoc`.
Your server can create a collaborative room from a .docx before any browser
connects, and export a live room without one. Requires `jsdom`.

### Breaking

* **`yjs` and `y-protocols` are now peer dependencies** and are no longer
  bundled. Install them yourself, and make sure your bundler resolves ONE copy
  — Yjs identifies its own types with `instanceof`, so a second copy breaks a
  shared document. Only collaboration needs them; they are optional peers.
* **`ReviseDocumentInput.docx` is now optional**, since a document joining a
  collaborative room needs no source file. Inputs must supply `docx`,
  `collaboration`, or both.

### Fixed

* `search_result_id`, which the agent tool schemas advertise for bulk edits,
  was unusable: tool state did not survive between `tools.execute()` calls.
* `exportDocx()` omitted TOC page numbers, which only the live layout knows.
* Exports lost imported named styles and reset core property dates in any
  non-browser environment.
* `collaboration.synced` was read once at mount, so a host reporting sync
  later was ignored and the document never opened.
* The margin insert-comment chip was missing from the embedded editor.
* Presence colors: an explicit `currentUser.color` was ignored whenever the
  user had an id.

## 0.2.0

Multi-document sessions, host-owned chrome, skinning props, per-embed
theming, the selection controller, and comment-thread agents.

## 0.1.0

First release: the editor, DOCX in and out, tracked changes, comments, and
the agent tool surface.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.