revise 1.0.0 → 2.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 (104) hide show
  1. package/CHANGELOG.md +962 -0
  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 +39 -1
  12. package/THIRD-PARTY-NOTICES.md +3376 -0
  13. package/assets/historyMaterializeWorker-CoAX9ZAi.js +3 -0
  14. package/backend.d.ts +133 -0
  15. package/backend.js +1 -0
  16. package/chunks/AgentPageRenderer-C0n4EnuW.js +1 -0
  17. package/chunks/AgentPageRenderer-DURfmiu0.js +1 -0
  18. package/chunks/AttachmentDocumentImporter-DSic_6At.js +1 -0
  19. package/chunks/AttachmentDocumentImporter-dNMtkxrv.js +1 -0
  20. package/chunks/BidiText-B4Hzrjg9.js +1 -0
  21. package/chunks/ColorParserFull-BKH72fK8.js +1 -0
  22. package/chunks/DocumentStylesheet-byN5dtC6.js +1 -0
  23. package/chunks/DocxConverter-B7P52lw7.js +11 -0
  24. package/chunks/DocxConverter-COV6CjUM.js +11 -0
  25. package/chunks/DocxConverter-Cq_zCEJC.js +11 -0
  26. package/chunks/DocxGraft-CJ12C9WP.js +1 -0
  27. package/chunks/DocxGraft-CQpvFcYb.js +1 -0
  28. package/chunks/DocxGraft-DcmFuUkd.js +1 -0
  29. package/chunks/FileImporter-DVnYOJHp.js +1 -0
  30. package/chunks/FileImporter-q9mCch0J.js +1 -0
  31. package/chunks/HorizontalRuleOrnaments-gmUZ3R7Q.js +1 -0
  32. package/chunks/HtmlConverter-JvRlkQM3.js +61 -0
  33. package/chunks/ListNumbering-Qlu6AuRZ.js +1 -0
  34. package/chunks/MarkdownConverter-B-tPY7X3.js +17 -0
  35. package/chunks/MathRenderer-B0Y1h1JU.js +33 -0
  36. package/chunks/OdtConverter-Br81BSoJ.js +1 -0
  37. package/chunks/OdtConverter-CQjh0vlo.js +1 -0
  38. package/chunks/OdtConverter-DYHnR4E8.js +1 -0
  39. package/chunks/PdfConverter-D26rXumc.js +21 -0
  40. package/chunks/PdfConverter-DGZpUSVf.js +21 -0
  41. package/chunks/PdfConverter-DZzVP0-B.js +21 -0
  42. package/chunks/PdfImportService-CBD8TL1k.js +2 -0
  43. package/chunks/PdfImportService-D6uUKGMf.js +2 -0
  44. package/chunks/RtfConverter-BQGge3K-.js +14 -0
  45. package/chunks/RtfConverter-CMfZ4olw.js +14 -0
  46. package/chunks/RtfConverter-oIwzoqCD.js +14 -0
  47. package/chunks/TableBorders-BLkZYt1k.js +1 -0
  48. package/chunks/TableGrid-DVWaRZv0.js +1 -0
  49. package/chunks/TextFileDecoder--rsVs3NR.js +2 -0
  50. package/chunks/TxtConverter-C1lp6dBS.js +11 -0
  51. package/chunks/__vite-browser-external-l0sNRNKZ.js +0 -0
  52. package/chunks/_commonjsHelpers-DaMA6jEr.js +1 -0
  53. package/chunks/_revise-sdk-lazy-harfbuzz-CDWdjF9f.js +1 -0
  54. package/chunks/_revise-sdk-lazy-harfbuzz-X8gnYTZL.js +1 -0
  55. package/chunks/ar-kgSWdrXF.js +8 -0
  56. package/chunks/backend-Cq-khfdG.js +1 -0
  57. package/chunks/base64-CfDUyGi8.js +36 -0
  58. package/chunks/browser-module-6b2Fq-5C.js +3 -0
  59. package/chunks/browser-module-CFmqfGkE.js +3 -0
  60. package/chunks/browser-module-CkO57IPL.js +3 -0
  61. package/chunks/bundle.min-DRpfgV69.js +8 -0
  62. package/chunks/capture-DU3MC7tb.js +1 -0
  63. package/chunks/carrier-WgcRSu7a.js +1 -0
  64. package/chunks/de-C2QTHrqo.js +8 -0
  65. package/chunks/es-BKboUn4q.js +8 -0
  66. package/chunks/footnoteFlatten-CW-DUcgK.js +1 -0
  67. package/chunks/graftExport-CVg7PO2A.js +2 -0
  68. package/chunks/html2canvas.esm-CntiHiYW.js +5 -0
  69. package/chunks/index-BWdRWxoH.js +24 -0
  70. package/chunks/index-CLw_BlSL.js +353 -0
  71. package/chunks/index-F-kHIwWT.js +353 -0
  72. package/chunks/index.es-CI0QPo8w.js +5 -0
  73. package/chunks/index.es-DOqegDGr.js +5 -0
  74. package/chunks/index.es-tXDO0RMv.js +5 -0
  75. package/chunks/jspdf.es.min-CzYti8jo.js +77 -0
  76. package/chunks/jspdf.es.min-DU74zN8b.js +77 -0
  77. package/chunks/jspdf.es.min-ejWOGhkJ.js +77 -0
  78. package/chunks/jszip.min-CPW0h1Kx.js +2 -0
  79. package/chunks/katex-DWj8TvwO.js +261 -0
  80. package/chunks/pdf-BLWDCiFF.js +12 -0
  81. package/chunks/persistInlineDocumentImages-DQj2iaqg.js +1 -0
  82. package/chunks/pseudoLocale-CdBtPHRi.js +1 -0
  83. package/chunks/pseudoLocale-DEVWLkGC.js +1 -0
  84. package/chunks/purify.es-BwLardii.js +2 -0
  85. package/chunks/serverDocumentSession-DZrYbdpk.js +42 -0
  86. package/chunks/tree-sitter-D6zWWUMP.js +4 -0
  87. package/chunks/wasmInline.generated-CBYFkdSM.js +1 -0
  88. package/chunks/web-tree-sitter-BXGZGnNj.js +1 -0
  89. package/full.js +1 -0
  90. package/index.d.ts +929 -0
  91. package/index.js +1 -0
  92. package/package.json +93 -26
  93. package/root.d.ts +5 -0
  94. package/root.js +2 -0
  95. package/serverToolContract.d.ts +373 -0
  96. package/serverToolInputs.generated.d.ts +229 -0
  97. package/style.css +1 -0
  98. package/.npmignore +0 -4
  99. package/.travis.yml +0 -16
  100. package/revise.js +0 -16
  101. package/t/cover +0 -18
  102. package/t/revise/comparator.t.js +0 -31
  103. package/t/revise/extractor.t.js +0 -29
  104. package/t/test +0 -20
package/index.d.ts ADDED
@@ -0,0 +1,929 @@
1
+ import * as React from "react";
2
+ // The canonical tool contract, shared verbatim with the backend entry: the
3
+ // browser surface returns the same envelopes and throws the same error.
4
+ import type {
5
+ ReviseSuggestionDecision,
6
+ ReviseToolInput,
7
+ ReviseToolName,
8
+ ReviseToolResponse,
9
+ ReviseToolResult,
10
+ } from "./serverToolContract.js";
11
+ export type * from "./serverToolContract.js";
12
+
13
+ export declare class ReviseToolError<Name extends string = string> extends Error {
14
+ readonly failure: import("./serverToolContract.js").ReviseToolFailure<Name>;
15
+ readonly callId: string;
16
+ readonly tool: Name;
17
+ readonly code: string;
18
+ constructor(failure: import("./serverToolContract.js").ReviseToolFailure<Name>);
19
+ }
20
+
21
+ /** The version of this package, at runtime. Include it when you escalate. */
22
+ export declare const REVISE_SDK_VERSION: string;
23
+
24
+ /** The commit this bundle was built from. Empty in a development build. */
25
+ export declare const REVISE_SDK_BUILD: string;
26
+
27
+ export interface ReviseDocument {
28
+ type: "doc";
29
+ children: unknown[];
30
+ [key: string]: unknown;
31
+ }
32
+
33
+ export interface EditorUserIdentity {
34
+ id?: string;
35
+ name?: string;
36
+ email?: string;
37
+ image?: string;
38
+ /** Caret and presence color. Any CSS color. Without one, a stable color
39
+ * is derived from the id. */
40
+ color?: string;
41
+ }
42
+
43
+ export interface ReviseAgentMessage {
44
+ role: string;
45
+ content: string;
46
+ timestamp?: number;
47
+ toolName?: string;
48
+ incomplete?: boolean;
49
+ [key: string]: unknown;
50
+ }
51
+
52
+ export interface ReviseAgentTurnRequest {
53
+ prompt: string;
54
+ currentDocument: ReviseDocument;
55
+ currentTurn: number;
56
+ config: Record<string, unknown>;
57
+ [key: string]: unknown;
58
+ }
59
+
60
+ export interface ReviseAgentStreamEvent {
61
+ type: "text" | "tool_call" | "tool_result" | "tool_start" | "usage" | "error" | "done" | "request_mode" | "web_search" | "reasoning" | "history_repair";
62
+ data: any;
63
+ }
64
+
65
+ export type ReviseAgentTurnStream = (
66
+ request: ReviseAgentTurnRequest,
67
+ ) => AsyncGenerator<ReviseAgentStreamEvent, void, unknown>;
68
+
69
+ export interface ReviseAgentConfig {
70
+ /** Display name for comments and tracked changes. Defaults to Revise Agent. */
71
+ name?: string;
72
+ baseUrl?: string;
73
+ token?: string;
74
+ conversationId?: string;
75
+ provider?: string;
76
+ model?: string;
77
+ turnStream?: ReviseAgentTurnStream;
78
+ disableMetrics?: boolean;
79
+ }
80
+
81
+ export interface ReviseAgentEvent {
82
+ state: "idle" | "streaming" | "complete" | "error";
83
+ activeTool: string | null;
84
+ status: string | null;
85
+ error?: string;
86
+ messages: ReviseAgentMessage[];
87
+ }
88
+
89
+ export interface ReviseAgentRunOptions {
90
+ /** Narrows host authority for this run; cannot raise it. */
91
+ executionPolicy?: {
92
+ documentAccess: "read" | "comment" | "edit";
93
+ interaction: "interactive" | "best_effort";
94
+ allowedTools?: readonly string[] | null;
95
+ };
96
+ developerPrePrompt?: string;
97
+ allowedToolNames?: string[];
98
+ providerOverride?: string;
99
+ modelOverride?: string;
100
+ forceFirstTurnNoTools?: boolean;
101
+ attachments?: unknown[];
102
+ directMode?: boolean;
103
+ }
104
+
105
+ export interface ReviseAgentRunResult extends ReviseAgentEvent {
106
+ actionCount: number;
107
+ }
108
+
109
+ export interface ReviseEditorToolDefinition {
110
+ name: string;
111
+ description: string;
112
+ inputSchema: Record<string, unknown>;
113
+ }
114
+
115
+ export interface ReviseEditorToolExecutionOptions {
116
+ /** Target an open document. Omit to use the active document. */
117
+ documentId?: string;
118
+ /** Apply mutation tools directly instead of leaving tracked suggestions. */
119
+ directMode?: boolean;
120
+ }
121
+
122
+ /** Tool arguments, with input optional only when its schema has no required
123
+ * fields — the browser twin of the server contract's argument tuple. */
124
+ export type ReviseEditorToolArguments<Name extends ReviseToolName> =
125
+ Record<string, never> extends ReviseToolInput<Name>
126
+ ? [input?: ReviseToolInput<Name>, options?: ReviseEditorToolExecutionOptions]
127
+ : [input: ReviseToolInput<Name>, options?: ReviseEditorToolExecutionOptions];
128
+
129
+ export interface ReviseEditorTool extends ReviseEditorToolDefinition {
130
+ execute(
131
+ input?: Record<string, unknown>,
132
+ options?: ReviseEditorToolExecutionOptions,
133
+ ): Promise<ReviseToolResult<string>>;
134
+ }
135
+
136
+ /** The document tool surface. Speaks the same contract as
137
+ * the backend entry: the same discriminated result envelope, the
138
+ * same typed inputs, the same execute/executeDynamic/call split. */
139
+ export interface ReviseEditorTools {
140
+ /** Execute a known tool; expected failures come back as { ok: false }. */
141
+ execute<Name extends ReviseToolName>(
142
+ name: Name,
143
+ ...args: ReviseEditorToolArguments<Name>
144
+ ): Promise<ReviseToolResult<Name>>;
145
+ /** Execute an untrusted model-provided name and JSON input; also the door
146
+ * to browser-only tools (get_selection, view_image, revise_run_agent) and
147
+ * model-facing document_id routing. */
148
+ executeDynamic(
149
+ name: string,
150
+ input?: Record<string, unknown>,
151
+ options?: ReviseEditorToolExecutionOptions,
152
+ ): Promise<ReviseToolResult<string>>;
153
+ /** Returns only the successful response and throws ReviseToolError when
154
+ * the tool rejects the call. */
155
+ call<Name extends ReviseToolName>(
156
+ name: Name,
157
+ ...args: ReviseEditorToolArguments<Name>
158
+ ): Promise<ReviseToolResponse<Name>>;
159
+ getDefinitions(): ReviseEditorToolDefinition[];
160
+ exportDocx(): Promise<Blob>;
161
+ /** Settle every open suggestion, collaborators' included. Prefer ID-based
162
+ * review.acceptSuggestions() with IDs from mutation results. */
163
+ acceptAllSuggestions(): ReviseSuggestionDecision;
164
+ rejectAllSuggestions(): ReviseSuggestionDecision;
165
+ }
166
+
167
+ export interface ReviseAgentSubagent {
168
+ run(task: string, options?: ReviseAgentRunOptions): Promise<ReviseAgentRunResult>;
169
+ steer(message: string): boolean;
170
+ cancel(): void;
171
+ subscribe(listener: (event: ReviseAgentEvent) => void): () => void;
172
+ }
173
+
174
+ export function createEmptyDocx(title?: string): Promise<Blob>;
175
+ /**
176
+ * Where Revise's static assets load from: PDF export and math fonts, the
177
+ * KaTeX stylesheet, the pdf.js worker, and (revise/editor/full) Tree-sitter
178
+ * grammars. Defaults to https://revise.io. To self-host, mirror revise.io's
179
+ * fonts/, katex.min.css, pdfjs/, and tree-sitter/ at your own origin and pass
180
+ * it here; null restores the default.
181
+ */
182
+ export declare function setAssetBaseUrl(url: string | null): void;
183
+
184
+ export type ReviseCommentAgentStatus =
185
+ | "running"
186
+ | "complete"
187
+ | "error"
188
+ | "interrupted"
189
+ | "canceled";
190
+
191
+ export interface ReviseCommentAgentState {
192
+ threadId: string;
193
+ status: ReviseCommentAgentStatus;
194
+ statusText?: string;
195
+ error?: string;
196
+ relatedSuggestionIds?: string[];
197
+ updatedAt: number;
198
+ [key: string]: unknown;
199
+ }
200
+
201
+ export interface ReviseCommentAgentRunResult {
202
+ threadId: string;
203
+ status: ReviseCommentAgentStatus;
204
+ reply?: string;
205
+ relatedSuggestionIds: string[];
206
+ error?: string;
207
+ }
208
+
209
+ export interface ReviseCommentAgent {
210
+ run(threadId: string, prompt?: string): Promise<ReviseCommentAgentRunResult>;
211
+ steer(threadId: string, message: string): boolean;
212
+ cancel(threadId: string): void;
213
+ getState(threadId: string): ReviseCommentAgentState | undefined;
214
+ subscribe(
215
+ listener: (states: ReadonlyMap<string, ReviseCommentAgentState>) => void,
216
+ ): () => void;
217
+ }
218
+
219
+ export type InlineFormattingCommand =
220
+ | "bold"
221
+ | "italic"
222
+ | "underline"
223
+ | "strikethrough"
224
+ | "doubleStrikethrough"
225
+ | "smallCaps"
226
+ | "allCaps"
227
+ | "code"
228
+ | "latex"
229
+ | "superscript"
230
+ | "subscript";
231
+
232
+ export type ReviseToolbarMode = "native" | "none";
233
+ export type ReviseZoom = number | "fit-width";
234
+
235
+ export interface ReviseFontDefinition {
236
+ family: string;
237
+ label?: string;
238
+ cssFamily?: string;
239
+ fontWeight?: number | string;
240
+ }
241
+
242
+ export interface ReviseZoomState {
243
+ zoom: ReviseZoom;
244
+ scale: number;
245
+ }
246
+
247
+ export interface ReviseEditorZoomController {
248
+ getState(): ReviseZoomState;
249
+ setZoom(zoom: ReviseZoom): void;
250
+ fitWidth(): void;
251
+ subscribe(listener: (state: ReviseZoomState) => void): () => void;
252
+ }
253
+
254
+ export interface ReviseSelectionPosition {
255
+ kind: "text";
256
+ blockId: string;
257
+ offset: number;
258
+ }
259
+
260
+ export interface ReviseTextTargetSegment {
261
+ blockId: string;
262
+ range: { start: number; end: number };
263
+ }
264
+
265
+ export interface ReviseTextTarget {
266
+ kind: "text";
267
+ segments: ReviseTextTargetSegment[];
268
+ }
269
+
270
+ export interface ReviseSelectionTarget {
271
+ kind: "selection";
272
+ start: ReviseSelectionPosition;
273
+ end: ReviseSelectionPosition;
274
+ }
275
+
276
+ export interface ReviseSelectionSnapshot {
277
+ documentId: string | null;
278
+ anchor: ReviseSelectionPosition | null;
279
+ focus: ReviseSelectionPosition | null;
280
+ start: ReviseSelectionPosition | null;
281
+ end: ReviseSelectionPosition | null;
282
+ target: ReviseTextTarget | null;
283
+ selectionTarget: ReviseSelectionTarget | null;
284
+ activeMarks: string[];
285
+ activeCommentIds: string[];
286
+ activeChangeIds: string[];
287
+ quotedText: string;
288
+ text: string;
289
+ collapsed: boolean;
290
+ empty: boolean;
291
+ }
292
+
293
+ export type ReviseSelectionCapture = ReviseSelectionSnapshot & {
294
+ documentId: string;
295
+ target: ReviseTextTarget;
296
+ selectionTarget: ReviseSelectionTarget;
297
+ };
298
+
299
+ export type ReviseSelectionRestoreResult =
300
+ | { success: true }
301
+ | {
302
+ success: false;
303
+ reason: "not-ready" | "read-only" | "missing-target" | "stale";
304
+ };
305
+
306
+ export interface ReviseEditorSelection {
307
+ getSnapshot(): ReviseSelectionSnapshot;
308
+ subscribe(listener: (event: { snapshot: ReviseSelectionSnapshot }) => void): () => void;
309
+ observe(listener: (snapshot: ReviseSelectionSnapshot) => void): () => void;
310
+ capture(): ReviseSelectionCapture | null;
311
+ restore(capture: ReviseSelectionCapture): ReviseSelectionRestoreResult;
312
+ clear(): void;
313
+ }
314
+
315
+ export interface ReviseToolbarState {
316
+ ready: boolean;
317
+ readOnly: boolean;
318
+ documentMode: ReviseDocumentMode;
319
+ activeTab: "edit" | "layout" | "insert" | "tools" | "review";
320
+ hasSelection: boolean;
321
+ canUndo: boolean;
322
+ canRedo: boolean;
323
+ formatting: Record<string, unknown> & {
324
+ bold?: boolean;
325
+ italic?: boolean;
326
+ underline?: boolean;
327
+ strikethrough?: boolean;
328
+ color?: string;
329
+ backgroundColor?: string;
330
+ fontFamily?: string;
331
+ };
332
+ heading?: 1 | 2 | 3 | 4 | 5 | 6;
333
+ alignment?: "left" | "center" | "right" | "justify";
334
+ lineSpacing?: number;
335
+ fontSizePt?: number;
336
+ blockType: { type: string; variant?: string } | null;
337
+ review: {
338
+ open: boolean;
339
+ targetCount: number;
340
+ currentTargetSuggestionCount: number;
341
+ allOpenSuggestionCount: number;
342
+ showRemovals: boolean;
343
+ viewMode: "all-markup" | "final" | "original";
344
+ };
345
+ }
346
+
347
+ export interface ReviseDocumentStatistics {
348
+ wordCount: number;
349
+ characterCount: number;
350
+ }
351
+
352
+ /**
353
+ * DOCX-mode fidelity: what relationship the next export has to the original
354
+ * .docx file.
355
+ *
356
+ * "exact" — byte-identical to the imported file
357
+ * "grafted" — original bytes plus this document's edits; untouched
358
+ * content exports byte-for-byte
359
+ * "converted" — no usable original; export regenerates everything
360
+ */
361
+ export type ReviseSourceFidelity = "exact" | "grafted" | "converted";
362
+
363
+ export interface ReviseSourceFidelityReport {
364
+ fidelity: ReviseSourceFidelity;
365
+ /** Body blocks an export would regenerate (empty for "exact"). */
366
+ regeneratedBlockIds: string[];
367
+ /** Part domains an export would regenerate (notes, chrome, comments…). */
368
+ changedDomains: string[];
369
+ /** Why "converted", when it is. */
370
+ convertedReason?:
371
+ | "no-capture"
372
+ | "no-carrier"
373
+ | "carrier-hash-mismatch"
374
+ | "unpaired-capture";
375
+ }
376
+
377
+ export interface ReviseEditorToolbar {
378
+ getState(): ReviseToolbarState;
379
+ subscribe(listener: (state: ReviseToolbarState) => void): () => void;
380
+ /** Switches the ribbon row. "tools" is Revise-app chrome and is ignored in
381
+ * the SDK — use `getStatistics()` for word and character counts. */
382
+ setActiveTab(tab: ReviseToolbarState["activeTab"]): void;
383
+ openFind(): void;
384
+ undo(): boolean;
385
+ redo(): boolean;
386
+ copy(): Promise<void>;
387
+ copyAs(format: "plaintext" | "markdown" | "html"): Promise<void>;
388
+ cut(): boolean;
389
+ paste(): Promise<boolean>;
390
+ pasteTextOnly(): Promise<boolean>;
391
+ pasteFormattingOnly(): Promise<boolean>;
392
+ toggleInline(command: InlineFormattingCommand): boolean;
393
+ toggleBold(): boolean;
394
+ toggleItalic(): boolean;
395
+ toggleUnderline(): boolean;
396
+ toggleStrikethrough(): boolean;
397
+ toggleDoubleStrikethrough(): boolean;
398
+ toggleSmallCaps(): boolean;
399
+ toggleAllCaps(): boolean;
400
+ toggleCode(): boolean;
401
+ toggleLatex(): boolean;
402
+ toggleSuperscript(): boolean;
403
+ toggleSubscript(): boolean;
404
+ clearFormatting(): boolean;
405
+ setFontFamily(fontFamily?: string): boolean;
406
+ setFontSize(fontSizePt?: number): boolean;
407
+ setLetterSpacing(spacing?: number): boolean;
408
+ setTextColor(color?: string): boolean;
409
+ setHighlightColor(color?: string): boolean;
410
+ setHeading(level?: 1 | 2 | 3 | 4 | 5 | 6): boolean;
411
+ setAlignment(alignment?: "left" | "center" | "right" | "justify"): boolean;
412
+ setLineSpacing(spacing?: number): boolean;
413
+ toggleList(variant: "ordered" | "unordered" | "todo"): boolean;
414
+ createLink(): boolean;
415
+ increaseIndent(): boolean;
416
+ decreaseIndent(): boolean;
417
+ insertTable(rows: number, columns: number): boolean;
418
+ insertImage(file: File): Promise<boolean>;
419
+ insertContainer(): boolean;
420
+ insertCodeBlock(language?: string): boolean;
421
+ insertMathBlock(content?: string): boolean;
422
+ insertDiagram(content?: string): boolean;
423
+ insertFootnote(kind?: "footnote" | "endnote"): boolean;
424
+ insertPageNumber(): boolean;
425
+ insertPageBreak(): boolean;
426
+ insertSectionBreak(): boolean;
427
+ openReview(): void;
428
+ closeReview(): void;
429
+ reviewPrevious(): boolean;
430
+ reviewNext(): boolean;
431
+ acceptCurrent(): boolean;
432
+ rejectCurrent(): boolean;
433
+ acceptAll(): boolean;
434
+ rejectAll(): boolean;
435
+ setShowRemovals(show: boolean): void;
436
+ setSuggestionViewMode(mode: "all-markup" | "final" | "original"): void;
437
+ }
438
+
439
+ export interface ReviseCommentMention {
440
+ id: string;
441
+ type: "user" | "agent";
442
+ label: string;
443
+ start: number;
444
+ end: number;
445
+ email?: string;
446
+ }
447
+
448
+ export interface ReviseCommentRecord {
449
+ id: string;
450
+ author: string;
451
+ initials?: string;
452
+ authorId?: string;
453
+ authorImageUrl?: string;
454
+ createdAt: string;
455
+ bodyMd: string;
456
+ mentions?: ReviseCommentMention[];
457
+ parentId?: string;
458
+ relatedSuggestionIds?: string[];
459
+ resolved?: boolean;
460
+ }
461
+
462
+ export interface ReviseCommentAnchor {
463
+ blockId: string;
464
+ start: number;
465
+ end: number;
466
+ }
467
+
468
+ export interface ReviseCommentThread {
469
+ root: ReviseCommentRecord;
470
+ replies: ReviseCommentRecord[];
471
+ anchor: ReviseCommentAnchor | null;
472
+ relatedSuggestionIds: string[];
473
+ }
474
+
475
+ export interface ReviseReviewState {
476
+ open: boolean;
477
+ commentsOpen: boolean;
478
+ targetCount: number;
479
+ currentTargetSuggestionCount: number;
480
+ allOpenSuggestionCount: number;
481
+ openSuggestionIds: string[];
482
+ currentSuggestionIds: string[];
483
+ visibleAgentSuggestionIds: string[];
484
+ activeCommentId: string | null;
485
+ showRemovals: boolean;
486
+ viewMode: "all-markup" | "final" | "original";
487
+ commentThreads: ReviseCommentThread[];
488
+ }
489
+
490
+ export interface ReviseEditorReview {
491
+ getState(): ReviseReviewState;
492
+ subscribe(listener: (state: ReviseReviewState) => void): () => void;
493
+ open(): void;
494
+ close(): void;
495
+ previous(): boolean;
496
+ next(): boolean;
497
+ nextAgentSuggestion(): boolean;
498
+ acceptCurrent(): boolean;
499
+ rejectCurrent(): boolean;
500
+ acceptAll(): boolean;
501
+ rejectAll(): boolean;
502
+ previewCurrent(mode: "accept" | "reject" | null): boolean;
503
+ previewAll(mode: "accept" | "reject" | null): boolean;
504
+ getOpenSuggestionIds(): string[];
505
+ /** Every pending change with its kind, author, timestamp, location, and
506
+ * text. A pull, not part of the subscribed state. */
507
+ listChanges(): ReviseTrackedChange[];
508
+ getChange(suggestionId: string): ReviseTrackedChange | null;
509
+ navigateToSuggestion(suggestionId: string): boolean;
510
+ navigateWithinSuggestions(suggestionIds: string[], direction: "previous" | "next"): boolean;
511
+ previewSuggestions(suggestionIds: string[], mode: "accept" | "reject" | null): void;
512
+ /** Per-ID outcome, same shape as the server surface: stale IDs land in
513
+ * missing; a role that may not resolve reports all unresolved. */
514
+ acceptSuggestions(suggestionIds: string[]): ReviseSuggestionDecision;
515
+ rejectSuggestions(suggestionIds: string[]): ReviseSuggestionDecision;
516
+ setShowRemovals(show: boolean): void;
517
+ setSuggestionViewMode(mode: "all-markup" | "final" | "original"): void;
518
+ openComments(): void;
519
+ closeComments(): void;
520
+ selectComment(commentId: string | null): boolean;
521
+ addCommentAtSelection(bodyMd: string, mentions?: ReviseCommentMention[]): string | null;
522
+ addCommentToRanges(ranges: ReviseCommentAnchor[], bodyMd: string, mentions?: ReviseCommentMention[]): string | null;
523
+ addCommentToBlock(blockId: string, bodyMd: string, mentions?: ReviseCommentMention[]): string | null;
524
+ addCommentForSuggestion(suggestionId: string, bodyMd: string, mentions?: ReviseCommentMention[]): string | null;
525
+ replyToComment(commentId: string, bodyMd: string, mentions?: ReviseCommentMention[]): string | null;
526
+ setCommentResolved(commentId: string, resolved: boolean): boolean;
527
+ deleteComment(commentId: string): boolean;
528
+ getRelatedSuggestionIds(commentId: string): string[];
529
+ acceptCommentSuggestions(commentId: string): ReviseSuggestionDecision;
530
+ rejectCommentSuggestions(commentId: string): ReviseSuggestionDecision;
531
+ }
532
+
533
+ /** Chrome the SDK no longer renders buttons for; the host drives it. */
534
+ export interface ReviseViewState {
535
+ ready: boolean;
536
+ title: string;
537
+ documentMode: ReviseDocumentMode;
538
+ readOnly: boolean;
539
+ commentsOpen: boolean;
540
+ /** Comment threads in the document, open panel or not. */
541
+ commentCount: number;
542
+ reviewOpen: boolean;
543
+ /** Suggestions and comment threads Review would step through. */
544
+ reviewTargetCount: number;
545
+ }
546
+
547
+ export interface ReviseEditorView {
548
+ getState(): ReviseViewState;
549
+ subscribe(listener: (state: ReviseViewState) => void): () => void;
550
+ setTitle(title: string): void;
551
+ setDocumentMode(mode: ReviseDocumentMode): void;
552
+ setCommentsOpen(open: boolean): void;
553
+ setReviewOpen(open: boolean): void;
554
+ }
555
+
556
+ export interface ReviseDocumentHandle {
557
+ readonly id: string;
558
+ readonly title: string;
559
+ tools: ReviseEditorTools;
560
+ toolbar: ReviseEditorToolbar;
561
+ review: ReviseEditorReview;
562
+ /** Title and the comments/review/document-mode chrome the host now owns. */
563
+ view: ReviseEditorView;
564
+ zoom: ReviseEditorZoomController;
565
+ selection: ReviseEditorSelection;
566
+ agent: ReviseAgentSubagent;
567
+ comments: ReviseCommentAgent;
568
+ /** Presence and sync state for a shared document. */
569
+ collaboration: ReviseCollaborationController;
570
+ /** What this participant is permitted to do. */
571
+ getRole(): ReviseDocumentRole;
572
+ getDocument(): ReviseDocument;
573
+ /** DOCX-mode fidelity of the next export relative to the original file.
574
+ * Computed on demand from content signatures; cheap enough for UI
575
+ * badges, not for per-keystroke calls. */
576
+ getSourceFidelity(): ReviseSourceFidelityReport;
577
+ /** Live word and character counts (text statistics, no layout pass). */
578
+ getStatistics(): ReviseDocumentStatistics;
579
+ getDocumentMode(): ReviseDocumentMode;
580
+ setDocumentMode(mode: ReviseDocumentMode): void;
581
+ getToolDefinitions(): ReviseEditorTool[];
582
+ focus(): void;
583
+ openReview(): void;
584
+ closeReview(): void;
585
+ openComments(): void;
586
+ closeComments(): void;
587
+ }
588
+
589
+ export type ReviseDocumentMode = "editing" | "suggesting" | "viewing";
590
+
591
+ export type ReviseDocumentSource = File | Blob | ArrayBuffer;
592
+
593
+ /** Input formats the SDK parses. DOCX is the only one carrying comments,
594
+ * tracked changes, sections, and headers. */
595
+ export type ReviseDocumentFormat = "docx" | "markdown" | "txt" | "html";
596
+
597
+ /**
598
+ * Yjs types, left deliberately loose.
599
+ *
600
+ * Naming them structurally made the package dependency-free but broke the
601
+ * thing hosts actually write: a `connect` callback annotated with the real
602
+ * `Y.Doc` is not assignable to a minimal stand-in, because callback
603
+ * parameters are contravariant. Declaring them permissively keeps your own
604
+ * code fully typed — annotate the callback with yjs's types, as you would
605
+ * anyway — without this package importing yjs for every consumer, including
606
+ * those who never collaborate.
607
+ */
608
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
609
+ export type ReviseYDoc = any;
610
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
611
+ export type ReviseAwareness = any;
612
+
613
+ /** Any Yjs provider: Hocuspocus exposes `document`, y-websocket and y-webrtc
614
+ * expose `doc`, and some wrappers expose `getYDoc()`. */
615
+ export interface ReviseCollaborationProvider {
616
+ document?: ReviseYDoc;
617
+ doc?: ReviseYDoc;
618
+ getYDoc?: () => ReviseYDoc;
619
+ awareness?: ReviseAwareness | null;
620
+ }
621
+
622
+ /** Attach a transport to a document the SDK built. Return the provider so the
623
+ * editor can recognize its transactions as remote. */
624
+ export type ReviseCollaborationConnect = (
625
+ ydoc: ReviseYDoc,
626
+ awareness: ReviseAwareness,
627
+ ) => ReviseCollaborationProvider | { destroy?: () => void } | void;
628
+
629
+ export interface ReviseCollaborationConfig {
630
+ /**
631
+ * The recommended form: the editor builds the document and awareness with
632
+ * the settings it requires, and this connects them.
633
+ *
634
+ * The editor reserves eight top-level keys in the document — content,
635
+ * chrome, notes, comments, annotations, metadata, sdt-wrappers, paragraphs
636
+ * — so a document built elsewhere may already use those names or hold
637
+ * another schema. Let the editor build its own.
638
+ */
639
+ connect?: ReviseCollaborationConnect;
640
+ /** A provider that already owns its document. The document is validated
641
+ * before use. */
642
+ provider?: ReviseCollaborationProvider;
643
+ /** A document you own. Validated before use; prefer `connect`. */
644
+ ydoc?: ReviseYDoc;
645
+ /** Awareness, for remote carets and presence. Pass null to opt out. */
646
+ awareness?: ReviseAwareness | null;
647
+ /** The transaction origin your transport applies remote updates with.
648
+ * Required when passing `ydoc` without a `provider`. */
649
+ remoteOrigin?: unknown;
650
+ /** Whether the transport has finished its initial sync. The document stays
651
+ * closed until this is true. */
652
+ synced?: boolean;
653
+ /** "if-empty" (default) writes the source file into an empty room;
654
+ * "never" always joins. */
655
+ seed?: "if-empty" | "never";
656
+ }
657
+
658
+ export interface RevisePeer {
659
+ clientId: number;
660
+ isLocal: boolean;
661
+ id?: string;
662
+ name?: string;
663
+ email?: string;
664
+ image?: string;
665
+ color: string;
666
+ }
667
+
668
+ export interface ReviseCollaborationState {
669
+ enabled: boolean;
670
+ synced: boolean;
671
+ peers: RevisePeer[];
672
+ }
673
+
674
+ export interface ReviseCollaborationController {
675
+ getState(): ReviseCollaborationState;
676
+ subscribe(listener: (state: ReviseCollaborationState) => void): () => void;
677
+ }
678
+
679
+ /** What a participant may do. A boundary, not a starting point: unlike
680
+ * `documentMode` it cannot be escaped from inside the editor. */
681
+ export type ReviseDocumentRole = "editor" | "suggester" | "viewer";
682
+
683
+ export interface ReviseRolePolicy {
684
+ readonly modes: readonly ReviseDocumentMode[];
685
+ readonly canEdit: boolean;
686
+ readonly canEditDirectly: boolean;
687
+ readonly canResolveSuggestions: boolean;
688
+ readonly canComment: boolean;
689
+ }
690
+
691
+ export declare function rolePolicy(role: ReviseDocumentRole): ReviseRolePolicy;
692
+
693
+ /** Thrown by `agent.run()` and UI controllers when a role forbids an
694
+ * action. Tool calls report role denials as structured
695
+ * `{ ok: false, error: { code: "role_not_permitted" } }` results instead. */
696
+ export declare class ReviseRoleError extends Error {
697
+ readonly role: ReviseDocumentRole;
698
+ readonly action: string;
699
+ }
700
+
701
+ /** A pending tracked change, with the metadata a review panel needs. */
702
+ export interface ReviseTrackedChange {
703
+ id: string;
704
+ /** Word's three revision kinds, plus "move" for a linked move pair. A
705
+ * replacement appears as both a delete and an insert, as it does in Word.
706
+ * A linked move is ONE change: `deletedText` is the text at the source,
707
+ * `insertedText` the text at the destination, and resolving it settles
708
+ * both locations atomically. */
709
+ kind: "insert" | "delete" | "format" | "move";
710
+ /** A person, "Revise Agent", an external agent, or "Anonymous". */
711
+ author: string;
712
+ authorType: "human" | "ai";
713
+ agentModel?: string;
714
+ /** Epoch milliseconds. */
715
+ createdAt?: number;
716
+ description?: string;
717
+ /** Blocks this change touches, in document order. */
718
+ blockIds: string[];
719
+ /** For kind "move": blocks the text moved out of, in document order. */
720
+ moveSourceBlockIds?: string[];
721
+ /** For kind "move": blocks the text moved into, in document order. */
722
+ moveDestinationBlockIds?: string[];
723
+ insertedText?: string;
724
+ deletedText?: string;
725
+ commentThreadId?: string;
726
+ }
727
+
728
+ export interface ReviseDocumentInput {
729
+ /** Stable host-owned ID used by APIs, agent tools, and callbacks. */
730
+ id: string;
731
+ /** The source document: DOCX, Markdown, plain text, or HTML. Optional when
732
+ * joining an established collaborative document. */
733
+ docx?: ReviseDocumentSource;
734
+ /** Share this document over a Yjs transport you own. */
735
+ collaboration?: ReviseCollaborationConfig;
736
+ /** Overrides the editor-wide role for this document. */
737
+ role?: ReviseDocumentRole;
738
+ /** Declare the format explicitly. Inferred from filename, then MIME type,
739
+ * defaulting to DOCX. */
740
+ format?: ReviseDocumentFormat;
741
+ title?: string;
742
+ documentMode?: ReviseDocumentMode;
743
+ readOnly?: boolean;
744
+ zoom?: ReviseZoom;
745
+ defaultCommentsOpen?: boolean;
746
+ /** Per-document agent settings override the editor-wide defaults. */
747
+ agent?: ReviseAgentConfig;
748
+ }
749
+
750
+ export interface ReviseOpenDocument {
751
+ id: string;
752
+ title: string;
753
+ status: "opening" | "ready" | "error";
754
+ active: boolean;
755
+ error?: string;
756
+ }
757
+
758
+ export interface ReviseDocumentCollectionState {
759
+ activeDocumentId: string | null;
760
+ documents: ReviseOpenDocument[];
761
+ }
762
+
763
+ export interface ReviseOpenDocumentOptions {
764
+ /** Newly opened documents become active by default. */
765
+ activate?: boolean;
766
+ }
767
+
768
+ export interface ReviseEditorDocuments {
769
+ open(
770
+ document: ReviseDocumentInput,
771
+ options?: ReviseOpenDocumentOptions,
772
+ ): Promise<ReviseDocumentHandle>;
773
+ close(documentId: string): boolean;
774
+ activate(documentId: string): boolean;
775
+ get(documentId?: string): ReviseDocumentHandle | null;
776
+ require(documentId?: string): ReviseDocumentHandle;
777
+ getActiveId(): string | null;
778
+ list(): ReviseOpenDocument[];
779
+ getState(): ReviseDocumentCollectionState;
780
+ subscribe(
781
+ listener: (state: ReviseDocumentCollectionState) => void,
782
+ ): () => void;
783
+ }
784
+
785
+ export type ReviseDocumentScoped<T> = T & {
786
+ /** Bind this controller to one open document instead of the active one. */
787
+ forDocument(documentId: string): T;
788
+ };
789
+
790
+ export interface ReviseMultiDocumentTools extends ReviseEditorTools {
791
+ forDocument(documentId: string): ReviseEditorTools;
792
+ exportDocx(documentId?: string): Promise<Blob>;
793
+ acceptAllSuggestions(documentId?: string): ReviseSuggestionDecision;
794
+ rejectAllSuggestions(documentId?: string): ReviseSuggestionDecision;
795
+ }
796
+
797
+ export interface ReviseEditorHandle {
798
+ documents: ReviseEditorDocuments;
799
+ /** Resolve an explicit document, or the active document when omitted. */
800
+ document(documentId?: string): ReviseDocumentHandle;
801
+ tools: ReviseMultiDocumentTools;
802
+ toolbar: ReviseDocumentScoped<ReviseEditorToolbar>;
803
+ review: ReviseDocumentScoped<ReviseEditorReview>;
804
+ /** Title and the comments/review/document-mode chrome the host now owns. */
805
+ view: ReviseDocumentScoped<ReviseEditorView>;
806
+ zoom: ReviseDocumentScoped<ReviseEditorZoomController>;
807
+ selection: ReviseDocumentScoped<ReviseEditorSelection>;
808
+ agent: ReviseDocumentScoped<ReviseAgentSubagent>;
809
+ comments: ReviseDocumentScoped<ReviseCommentAgent>;
810
+ /** Presence and sync state for shared documents. */
811
+ collaboration: ReviseDocumentScoped<ReviseCollaborationController>;
812
+ /** What this participant may do with a document. */
813
+ getRole(documentId?: string): ReviseDocumentRole;
814
+ /**
815
+ * Resolves once a document is open and its controllers are usable.
816
+ *
817
+ * `onReady` hands you the editor before any document exists; everything
818
+ * that acts on a document throws until one does. Subscriptions are the
819
+ * exception and can be placed immediately.
820
+ */
821
+ whenReady(documentId?: string): Promise<ReviseDocumentHandle>;
822
+ getDocument(documentId?: string): ReviseDocument;
823
+ /** Live word and character counts for a document (active by default). */
824
+ getStatistics(documentId?: string): ReviseDocumentStatistics;
825
+ getDocumentMode(documentId?: string): ReviseDocumentMode;
826
+ setDocumentMode(mode: ReviseDocumentMode, documentId?: string): void;
827
+ getToolDefinitions(documentId?: string): ReviseEditorTool[];
828
+ focus(documentId?: string): void;
829
+ openReview(documentId?: string): void;
830
+ closeReview(documentId?: string): void;
831
+ openComments(documentId?: string): void;
832
+ closeComments(documentId?: string): void;
833
+ }
834
+
835
+ /** Behavior settings for tracked changes. */
836
+ export interface ReviseTrackedChangesSettings {
837
+ /** Start review with deleted text shown inline (strikethrough). Reviewers
838
+ * used to Word usually want this on. Default false. */
839
+ showRemovalsInReview?: boolean;
840
+ /** "revise" (default): per-kind colors with a soft background tint.
841
+ * "word": classic redlines — all revisions in red, insertions underlined,
842
+ * deletions struck through, no background tint. */
843
+ markupStyle?: "revise" | "word";
844
+ }
845
+
846
+ export interface ReviseEditorSettings {
847
+ trackedChanges?: ReviseTrackedChangesSettings;
848
+ }
849
+
850
+ export interface ReviseEditorProps {
851
+ findShortcut?: "editor" | "browser";
852
+ /** Behavior settings. */
853
+ settings?: ReviseEditorSettings;
854
+ /** Receive the editor's internal instrumentation events (tool
855
+ * invocations, exports, review interactions, …) for the host's own
856
+ * analytics. These events never leave the page except through this
857
+ * callback. Event names and property shapes may change between versions. */
858
+ onAnalyticsEvent?: (
859
+ event: string,
860
+ properties?: Record<string, unknown>,
861
+ ) => void;
862
+ /** Once per page load, the SDK sends Revise one anonymous ping carrying
863
+ * its version; the browser adds your site's origin. Development hosts
864
+ * (localhost and similar) are only counted, never named. No cookies, user
865
+ * data, or document content. Set false to turn it off. Defaults to true. */
866
+ telemetry?: boolean;
867
+ initialDocuments?: readonly ReviseDocumentInput[];
868
+ /** Controlled active document ID. */
869
+ activeDocumentId?: string | null;
870
+ /** Initial active ID for uncontrolled use. Defaults to the first document. */
871
+ defaultActiveDocumentId?: string | null;
872
+ currentUser?: EditorUserIdentity | null;
873
+ agent?: ReviseAgentConfig;
874
+ theme?: "light" | "dark";
875
+ /** What this participant may do, across every open document. Overridden per
876
+ * document by `ReviseDocumentInput.role`. */
877
+ role?: ReviseDocumentRole;
878
+ defaultDocumentMode?: ReviseDocumentMode;
879
+ defaultZoom?: ReviseZoom;
880
+ defaultCommentsOpen?: boolean;
881
+ showDocumentModeToggle?: boolean;
882
+ /**
883
+ * Render the built-in tab strip (one tab per open document). Off by default:
884
+ * hosts with their own file switcher drive `documents` instead.
885
+ */
886
+ showTabs?: boolean;
887
+ /**
888
+ * Render the built-in title bar above the ribbon. Hosts that build their own
889
+ * chrome turn this off and drive `view` (title, mode, review) themselves.
890
+ */
891
+ showTitleBar?: boolean;
892
+ /** Adds a "+" button to the tab strip. Without it, no button is rendered. */
893
+ onNewTab?: () => void;
894
+ /**
895
+ * Take keyboard focus when a document becomes active. Defaults to true; set
896
+ * false when the editor sits inside a larger page and should wait for a click.
897
+ */
898
+ autoFocus?: boolean;
899
+ /** Opt in to the Rust/WASM hot paths (word diff, agent text matching,
900
+ * document stats). Off by default; the TypeScript implementations remain the
901
+ * fallback, so this only ever changes speed, never behavior. Available only
902
+ * from the explicit `revise/editor/full` entry point. */
903
+ wasmHotPaths?: boolean;
904
+ /** The area behind the page — not the page itself. Any CSS background. */
905
+ canvasBackground?: string;
906
+ /** The paper color. Any CSS color. */
907
+ pageBackground?: string;
908
+ /** The 1px outline around each page. Any CSS color. */
909
+ pageBorderColor?: string;
910
+ toolbarMode?: ReviseToolbarMode;
911
+ fonts?: readonly ReviseFontDefinition[];
912
+ className?: string;
913
+ style?: React.CSSProperties;
914
+ onReady?: (editor: ReviseEditorHandle) => void;
915
+ onDocumentReady?: (document: ReviseDocumentHandle) => void;
916
+ onDocumentsChange?: (state: ReviseDocumentCollectionState) => void;
917
+ onActiveDocumentChange?: (documentId: string | null) => void;
918
+ onChange?: (documentId: string, document: ReviseDocument) => void;
919
+ onDocumentTitleChange?: (documentId: string, title: string) => void;
920
+ onDocumentModeChange?: (documentId: string, mode: ReviseDocumentMode) => void;
921
+ onZoomChange?: (documentId: string, zoom: ReviseZoom) => void;
922
+ onAgentEvent?: (documentId: string, event: ReviseAgentEvent) => void;
923
+ onError?: (error: Error, documentId?: string) => void;
924
+ }
925
+
926
+ export const ReviseEditor: React.ForwardRefExoticComponent<
927
+ ReviseEditorProps & React.RefAttributes<ReviseEditorHandle>
928
+ >;
929
+ export default ReviseEditor;