@docx-editor.dev/editor-api/agent

Helpers for AI agents that edit documents through the editing API.

prepareRewrite reads a paragraph into text for a model, and draft.apply() proposes the model's new text as the fewest tracked changes. Fields, pictures, equations, note references, and locked content controls reach the model as numbered placeholders, so they change whole or not at all. Either every change lands and the paragraph reads as the model text, or the paragraph stays as it was and apply() throws a RewriteError with a stable code.

You own the model call: the prompt, the instruction, retries, timeouts, and concurrency. The helpers own only the document side, which is deterministic.

The helpers sit next to the object model, not on it, and are outside its Office.js compatibility scope. They use only the Office.js-shaped calls of @docx-editor.dev/editor-api, on the context and paragraph that you pass in.

Functions (1)

prepareRewritefunctionSource ↗

Read a paragraph for a model. The draft is plain data: build a prompt from draft.text and draft.legend with your own instruction, call your model, and pass its text to draft.apply() in the same run(). draft.check() tests model text without writing.

The helper never calls a model and never retries. It reads the paragraph, checks model text, and writes the fewest tracked changes, all or nothing.

Throws a [RewriteError](RewriteError): pending-changes when the paragraph has tracked changes, tracking-unavailable when the runtime has no author, too-long or unsupported-text when the paragraph cannot be compared, read-failed when the document refuses a read, busy when another helper call runs on the context, and context-used when edits are queued on it.

declare function prepareRewrite(context: RequestContext, paragraph: Paragraph, options?: PrepareRewriteOptions): Promise<RewriteDraft>;
```ts
const draft = await prepareRewrite(context, paragraph);
const prompt = `Make this paragraph formal.\n\n${draft.legend}\n\n${draft.text}`;
const result = await draft.apply(await callModel(prompt));
```

Classes (1)

RewriteErrorclassSource ↗

A refused or failed rewrite. Every code except rollback-failed leaves the paragraph as it was before the rewrite.

declare class RewriteError extends Error
```ts
try {
  const draft = await prepareRewrite(context, paragraph);
  await draft.apply(await callModel(`${draft.legend}\n\n${draft.text}`));
} catch (error) {
  if (error instanceof RewriteError && error.code === 'pending-changes') {
    // Decide the tracked changes in the paragraph first.
  } else throw error;
}
```
MemberTypeSummary
(constructor)Constructs a new instance of the `RewriteError` class
codeRewriteErrorCodeWhat went wrong. See [RewriteErrorCode](RewriteErrorCode) for what to do next.
isModelErrorbooleanWhether the model output broke a rule. The message then explains the rule in words that you can send back to the model.
nameAlways `'RewriteError'`.
suppressed?unknownA second error that happened while the helper cleaned up after this one, such as a failure to turn tracking off again. It never replaces this error.

Interfaces (4)

PrepareRewriteOptionsinterfaceSource ↗

How to read the paragraph and check the model text.

interface PrepareRewriteOptions
MemberTypeSummary
keepPlaceholders?booleanRefuse model text that leaves out a placeholder, with `placeholder-missing`. By default, a left-out placeholder deletes what it stands for as one tracked deletion. `draft.legend` states the rule that applies.

RewriteDraftinterfaceSource ↗

A paragraph read for a model: plain data, plus check() and apply() for the model text.

Build the prompt from text and legend with your own instruction, and call your model. Then call apply() in the same run() as prepareRewrite.

interface RewriteDraft
MemberTypeSummary
applyPropose the model text as the fewest tracked changes. Either every change lands and the paragraph reads as the model text, or the paragraph stays as it was and this throws a [RewriteError](RewriteError). After a model error, you can call it again with new model text. Call it once at a time on a request context: a helper call that overlaps another throws `busy`.
checkCheck model text without writing. Returns the [RewriteError](RewriteError) that `apply()` would throw before it writes, or `null` when `apply()` may go ahead. Most often the error is a model error (`error.isModelError`), whose message you can send back to the model. It can also be `draft-used`; `too-long`, when the text makes too many edits to compare; or `verification-failed`, when the text differs only in spacing that the helper cannot write.
legendstringThe placeholder contract as plain text for a prompt: what a placeholder is, the rules (copy each kept placeholder exactly, leave one out to delete it, keep the order, do not repeat one), and one line per placeholder, such as `⟦1⟧ = equation`. An empty string when `text` has no placeholder.
originalstringThe paragraph text as it reads now.
paragraphIdstringThe paragraph's `uniqueLocalId`.
placeholdersreadonly RewritePlaceholder[]Each placeholder in `text`, in order, and what it stands for.
textstringThe paragraph text with each field, picture, equation, note reference, line break, and locked control as a placeholder, such as `Subject to ⟦1⟧, the fee applies`. A paragraph that already contains `⟦` or `⟧` gets another bracket pair, such as `⟪1⟫`; read the exact placeholders from `placeholders`.

RewritePlaceholderinterfaceSource ↗

One placeholder in the draft text, and what it stands for.

interface RewritePlaceholder
MemberTypeSummary
descriptionstringA description for the model, such as `field REF _Ref1 \h, reads "Section 4.2"`, `equation`, or `locked content control "party", reads "Acme Corp"`.
kindRewritePlaceholderKindWhat the placeholder stands for.
placeholderstringThe placeholder as the model sees it, such as `⟦1⟧`.
textstringThe text the paragraph reads for it: a field result, a control's text, U+000B for a line break, or U+FFFC for an equation, a picture, or a note reference.

RewriteResultinterfaceSource ↗

What a proposed rewrite changed. Plain data.

interface RewriteResult
MemberTypeSummary
changesnumberHow many word edits the helper wrote: each run of changed words counts once. A replacement counts once, though `revisions.items` lists it as a `Delete` and an `Insert`. `0` when the model changed nothing.
originalstringThe text before the rewrite: what rejecting every proposed change gives.
paragraphIdstringThe paragraph's `uniqueLocalId`.
proposedstringThe text after the rewrite: what accepting every proposed change gives. As in `getReviewedText`, an equation, a picture, or a note reference reads as U+FFFC, and a line break as U+000B.

Type aliases (2)

RewriteErrorCodetypeSource ↗

Why a rewrite was refused or failed.

- The model text broke a rule, and nothing was written. draft.check() returns these too. Send error.message back to the model and ask again with the same draft: invalid-output, placeholder-missing, placeholder-unknown, placeholder-moved, placeholder-repeated, placeholder-grouped. - The request context is in use, and nothing was written: busy when another helper call runs on it, such as two apply() calls at once, and context-used when commands are queued on it that are not synced. - The paragraph cannot take a rewrite now, and nothing was written: pending-changes, tracking-unavailable, draft-used, too-long, unsupported-text, read-failed. - A write or the final check failed, and the helper rejected the changes it had written: stale, locked, write-failed, verification-failed. After stale or verification-failed, another edit moved the paragraph: prepare it again, and ask the model again with the new draft. - The rollback failed too, or could not find the paragraph after another edit joined or removed it, so the document can hold some of the proposal: rollback-failed. Do not retry automatically.

type RewriteErrorCode = 'invalid-output' | 'placeholder-missing' | 'placeholder-unknown' | 'placeholder-moved' | 'placeholder-repeated' | 'placeholder-grouped' | 'context-used' | 'busy' | 'pending-changes' | 'tracking-unavailable' | 'draft-used' | 'too-long' | 'unsupported-text' | 'read-failed' | 'stale' | 'locked' | 'write-failed' | 'verification-failed' | 'rollback-failed';

RewritePlaceholderKindtypeSource ↗

What a placeholder stands for.

type RewritePlaceholderKind = 'field' | 'content-control' | 'picture' | 'equation' | 'note-reference' | 'line-break';