revise 2.1.0 → 3.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.
- package/CHANGELOG.md +47 -1088
- package/LICENSE +24 -41
- package/README.md +103 -26
- package/agent.d.ts +139 -0
- package/chunks/chunk-U5X47PZ6.js +135 -0
- package/chunks/chunk-U6YKQBKL.js +15 -0
- package/chunks/chunk-ZLQVPMBN.js +1650 -0
- package/chunks/package-5SHL5FOJ.js +14 -0
- package/chunks/render-QD5VWKSV.js +109 -0
- package/cli-output.schema.json +1984 -0
- package/cli.js +3604 -0
- package/document.d.ts +320 -0
- package/docx.d.ts +73 -0
- package/errors.d.ts +14 -0
- package/index.d.ts +13 -967
- package/index.js +31 -1
- package/legacy/editor.d.ts +19 -0
- package/legacy/editor.js +16 -0
- package/legacy/server.d.ts +37 -0
- package/legacy/server.js +25 -0
- package/legacy/style.css +2 -0
- package/package.d.ts +23 -0
- package/package.json +49 -55
- package/render.d.ts +27 -0
- package/FONT-LICENSE-HAN-EXT-B.txt +0 -91
- package/FONT-LICENSE-KATEX.txt +0 -95
- package/FONT-LICENSE-LIBERATION.txt +0 -102
- package/FONT-LICENSE-NOTO-MULTILINGUAL.txt +0 -93
- package/FONT-LICENSE-NOTO-SANS-SC.txt +0 -93
- package/FONT-LICENSE-NOTO.txt +0 -94
- package/FONT-LICENSE-SOURCE-CODE-PRO.txt +0 -94
- package/FONT-LICENSE-SOURCE-SERIF-4.txt +0 -93
- package/THIRD-PARTY-NOTICES.md +0 -3376
- package/assets/historyMaterializeWorker-C4uxcZEh.js +0 -607
- package/backend.d.ts +0 -155
- package/backend.js +0 -3
- package/chunks/AgentPageRenderer-BFB0arQL.js +0 -1
- package/chunks/AgentPageRenderer-Dn6SaRjW.js +0 -1
- package/chunks/AttachmentDocumentImporter-BHDJAdky.js +0 -1
- package/chunks/AttachmentDocumentImporter-CxOZqzt1.js +0 -1
- package/chunks/BidiText-C8PBPSQY.js +0 -160
- package/chunks/ColorParserFull-BKH72fK8.js +0 -446
- package/chunks/DocumentMutator-4vBJQ74L.js +0 -31
- package/chunks/DocumentScrubber-COPepQKE.js +0 -1
- package/chunks/DocumentScrubber-Cf_QqHhF.js +0 -1
- package/chunks/DocumentScrubber-DS4LFDKS.js +0 -18
- package/chunks/DocumentStylesheet-byN5dtC6.js +0 -7
- package/chunks/DocxConverter-BCEB7jWY.js +0 -1083
- package/chunks/DocxConverter-C3NflpDr.js +0 -11
- package/chunks/DocxConverter-D9ZNn4nX.js +0 -11
- package/chunks/DocxGraft-Ba63IRP4.js +0 -1
- package/chunks/DocxGraft-DjERgl-z.js +0 -7
- package/chunks/DocxGraft-cYlmw4Ab.js +0 -1
- package/chunks/FileImporter-CHXj9sNX.js +0 -1
- package/chunks/FileImporter-DetvRoJc.js +0 -1
- package/chunks/HorizontalRuleOrnaments-gmUZ3R7Q.js +0 -3
- package/chunks/HtmlConverter-Sd9t49vH.js +0 -267
- package/chunks/ListNumbering-Qlu6AuRZ.js +0 -23
- package/chunks/MarkdownConverter-BdJgh8xt.js +0 -57
- package/chunks/MathRenderer-B0Y1h1JU.js +0 -62
- package/chunks/OdtConverter-BKtyx012.js +0 -1
- package/chunks/OdtConverter-Ce9j8PRt.js +0 -1
- package/chunks/OdtConverter-D709qfYb.js +0 -31
- package/chunks/ParagraphDiffAnalysis-DrmStvmz.js +0 -36
- package/chunks/PdfConverter-BA8XLTAM.js +0 -21
- package/chunks/PdfConverter-CkDClffR.js +0 -438
- package/chunks/PdfConverter-CxLxd-LJ.js +0 -21
- package/chunks/PdfImportService-CQCgsRX1.js +0 -2
- package/chunks/PdfImportService-xl7fstr-.js +0 -2
- package/chunks/RtfConverter-BZOnMUGH.js +0 -14
- package/chunks/RtfConverter-Bs81AfXt.js +0 -14
- package/chunks/RtfConverter-DfuE5olb.js +0 -45
- package/chunks/TableBorders-Cdkc62cX.js +0 -30
- package/chunks/TableGrid-DbroRucl.js +0 -12
- package/chunks/TextFileDecoder--rsVs3NR.js +0 -9
- package/chunks/TxtConverter-C-oiFUAp.js +0 -14
- package/chunks/UnicodeUtils-CXtusU4g.js +0 -10
- package/chunks/XmlConverter-C0FnrVYk.js +0 -70
- package/chunks/XmlConverter-CQa8baOF.js +0 -2
- package/chunks/XmlConverter-DjEYaIyf.js +0 -2
- package/chunks/__vite-browser-external-l0sNRNKZ.js +0 -0
- package/chunks/_commonjsHelpers-DaMA6jEr.js +0 -2
- package/chunks/_revise-sdk-lazy-harfbuzz-CDWdjF9f.js +0 -1
- package/chunks/_revise-sdk-lazy-harfbuzz-X8gnYTZL.js +0 -1
- package/chunks/ar-BdmGnaKI.js +0 -14
- package/chunks/backend-BIhAX-Gi.js +0 -484
- package/chunks/base64-Qx0OzT4p.js +0 -196
- package/chunks/browser-module-CFmqfGkE.js +0 -1791
- package/chunks/browser-module-CYGCfEyx.js +0 -3
- package/chunks/browser-module-DgvTMhpA.js +0 -3
- package/chunks/bundle.min-DRpfgV69.js +0 -782
- package/chunks/capture-BAJ2in5p.js +0 -9
- package/chunks/carrier-C5VZRMxZ.js +0 -6
- package/chunks/de-DldIXRFC.js +0 -14
- package/chunks/es-CnyKlSPK.js +0 -14
- package/chunks/footnoteFlatten-Bekh8ZfM.js +0 -6
- package/chunks/graftExport-CRRm1Oe_.js +0 -82
- package/chunks/html2canvas.esm-CntiHiYW.js +0 -997
- package/chunks/index-B1idHquf.js +0 -1094
- package/chunks/index-BWdRWxoH.js +0 -1807
- package/chunks/index-C-4H81OE.js +0 -378
- package/chunks/index-iZC8xN0t.js +0 -378
- package/chunks/index.es-Bwt05m_b.js +0 -5
- package/chunks/index.es-CI0QPo8w.js +0 -780
- package/chunks/index.es-DAQD57G4.js +0 -5
- package/chunks/jspdf.es.min-CnNRolk9.js +0 -77
- package/chunks/jspdf.es.min-DU74zN8b.js +0 -1792
- package/chunks/jspdf.es.min-DlTF8uTw.js +0 -77
- package/chunks/jszip.min-CPW0h1Kx.js +0 -476
- package/chunks/katex-DWj8TvwO.js +0 -1462
- package/chunks/pdf-BLWDCiFF.js +0 -1828
- package/chunks/persistInlineDocumentImages-DQj2iaqg.js +0 -1
- package/chunks/pseudoLocale-BoJwIubw.js +0 -1
- package/chunks/pseudoLocale-DWAm7Dpa.js +0 -1
- package/chunks/purify.es-BwLardii.js +0 -107
- package/chunks/serverDocumentSession-DASrQAbW.js +0 -15
- package/chunks/signatures-CBF7NZUy.js +0 -17
- package/chunks/tree-sitter-D6zWWUMP.js +0 -4
- package/chunks/wasmInline.generated-CBYFkdSM.js +0 -1
- package/chunks/web-tree-sitter-BXGZGnNj.js +0 -2
- package/full.js +0 -1
- package/root.d.ts +0 -5
- package/root.js +0 -2
- package/serverToolContract.d.ts +0 -391
- package/serverToolInputs.generated.d.ts +0 -250
- package/style.css +0 -1
package/LICENSE
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## Distribution and restrictions
|
|
26
|
-
|
|
27
|
-
You may bundle, minify, host, and distribute the compiled SDK within permitted apps, including to browsers. Preserve copyright and license notices. Recipients may run the embedded SDK within those apps. Standalone SDK resale, sublicensing, or redistribution—including reusable SDK wrappers—is prohibited without written permission.
|
|
28
|
-
|
|
29
|
-
Except to the extent applicable law expressly permits despite this restriction, you may not decompile, disassemble, reverse engineer, or modify the SDK, or attempt to derive its source code, algorithms, or internal structure. Configuring the SDK through its documented options is not modification. Revise retains ownership and all ungranted rights, and this license grants no rights to Revise names or logos except to identify the SDK; you retain your apps and documents. Third-party components retain their separate licenses.
|
|
30
|
-
|
|
31
|
-
The SDK sends an anonymous usage ping as described in its documentation; you may disable it.
|
|
32
|
-
|
|
33
|
-
## Termination
|
|
34
|
-
|
|
35
|
-
A material breach terminates your rights and requires you to stop using and distributing the SDK. Rights are reinstated if a first breach is fully cured within 30 days of written notice.
|
|
36
|
-
|
|
37
|
-
## Warranty and liability
|
|
38
|
-
|
|
39
|
-
TO THE EXTENT PERMITTED BY LAW, THE SDK IS PROVIDED “AS IS,” WITHOUT WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT, AND WITHOUT ANY SUPPORT OBLIGATION. REVISE AND ITS LICENSORS ARE NOT LIABLE FOR LOST PROFITS, LOST DATA, OR INDIRECT, INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES. THEIR TOTAL LIABILITY UNDER THIS LICENSE WILL NOT EXCEED US $100.
|
|
40
|
-
|
|
41
|
-
Ownership, restrictions, and warranty/liability provisions survive termination. A separate written agreement controls conflicting terms. Invalid provisions do not invalidate the remainder. Each version of the SDK is licensed under the license included with it. This license is governed by the laws of the State of Delaware, USA, excluding its conflict-of-laws rules.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Migraine, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
This package depends on @reviseio/engine, which is distributed separately
|
|
24
|
+
under its own license (free for any use, including commercial).
|
package/README.md
CHANGED
|
@@ -1,42 +1,119 @@
|
|
|
1
1
|
# revise
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The swiss army knife for documents. Read, edit, and redline Word documents
|
|
4
|
+
from the command line or from TypeScript. Edits land as tracked changes, with
|
|
5
|
+
comments, review, and undo, and untouched content is written back to the
|
|
6
|
+
.docx byte for byte. Built for AI agents and the programs that run them.
|
|
7
|
+
|
|
8
|
+
**Using a coding agent?** Paste this into it:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
Read https://revise.io/skills/cli.md and follow it.
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i -g revise # or: npx revise <command>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Node 20 or newer. No account, API key, or telemetry, and documents never
|
|
21
|
+
leave your machine. Two things fetch over the network: PDF export downloads
|
|
22
|
+
its fonts from revise.io, and an image you insert by URL is downloaded.
|
|
23
|
+
|
|
24
|
+
## The CLI
|
|
25
|
+
|
|
26
|
+
Every command names its file. Edits save the file in place.
|
|
4
27
|
|
|
5
28
|
```bash
|
|
6
|
-
|
|
29
|
+
revise outline contract.docx # headings with block ranges
|
|
30
|
+
revise read contract.docx 0 # blocks as HTML, with ids
|
|
31
|
+
revise replace-text contract.docx "Provider" "Northstar" # tracked change
|
|
32
|
+
revise changes contract.docx # what's pending
|
|
33
|
+
revise reject contract.docx --section 8 # review by section
|
|
34
|
+
revise export contract.docx contract.pdf # .docx .pdf .md .html .txt
|
|
35
|
+
revise compare v1.docx v2.docx --out redline.docx # redline two versions
|
|
36
|
+
revise undo contract.docx
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`revise tools` lists the editing tools (insert, replace, move, tables,
|
|
40
|
+
comments, footnotes, styles, headers and footers…) and `revise call` runs
|
|
41
|
+
one with JSON input. `--author "Legal bot"` signs tracked changes, `--out
|
|
42
|
+
copy.docx` saves an edit as a new file, and `-` reads or writes a pipe
|
|
43
|
+
(`cat notes.md | revise convert - notes.docx`). `--json` on any command prints
|
|
44
|
+
one versioned object ([contract](https://revise.io/developer/docs/revise/json)).
|
|
45
|
+
`revise examples` shows more.
|
|
46
|
+
|
|
47
|
+
## Agent skills
|
|
48
|
+
|
|
49
|
+
The skill teaches a coding agent the CLI: reading by block id, tracked edits,
|
|
50
|
+
review, creating documents, and the `xml` escape hatch.
|
|
51
|
+
|
|
52
|
+
| Agent | Install |
|
|
53
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| Claude Code | `claude plugin marketplace add reviseio/skills`, then `claude plugin install revise@revise` |
|
|
55
|
+
| Codex, ChatGPT desktop | `codex plugin marketplace add reviseio/skills`, then `codex plugin add revise@revise` |
|
|
56
|
+
| Cursor, Copilot, Windsurf, Cline… | `npx skills add reviseio/skills --skill revise` |
|
|
57
|
+
| Anything else | `revise skill install` (into `.agents/skills` or `.claude/skills`), or `revise skill` to print it |
|
|
58
|
+
|
|
59
|
+
Building a browser editor instead? The `revise-editor` skill covers
|
|
60
|
+
[`@reviseio/editor`](https://www.npmjs.com/package/@reviseio/editor):
|
|
61
|
+
`npx skills add reviseio/skills --skill revise-editor`.
|
|
62
|
+
|
|
63
|
+
## The library
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { ReviseDocument } from "revise";
|
|
67
|
+
|
|
68
|
+
const doc = await ReviseDocument.open("contract.docx", { author: "Legal bot" });
|
|
69
|
+
await doc.replaceText("Provider", "Northstar"); // tracked changes
|
|
70
|
+
await doc.reject({ section: "8" });
|
|
71
|
+
const { bytes, fidelity } = await doc.export({ format: "docx" });
|
|
72
|
+
doc.dispose();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Run the editing tools with typed input, or hand them to a model:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
79
|
+
import { ReviseDocument, agentTools } from "revise";
|
|
80
|
+
|
|
81
|
+
const doc = await ReviseDocument.open("brief.docx");
|
|
82
|
+
const { tools, handle } = agentTools(doc, { provider: "anthropic" });
|
|
83
|
+
const client = new Anthropic();
|
|
84
|
+
// Pass `tools` to client.messages.create(); answer each tool_use block in
|
|
85
|
+
// the response with `await handle(block)`, which returns its tool_result.
|
|
7
86
|
```
|
|
8
87
|
|
|
9
|
-
|
|
88
|
+
### Collaboration servers
|
|
10
89
|
|
|
11
|
-
|
|
90
|
+
Seed a sync server's room from a file, and edit or export the live room:
|
|
12
91
|
|
|
13
|
-
|
|
92
|
+
```ts
|
|
93
|
+
import { ReviseDocument, seedYDoc } from "revise";
|
|
14
94
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import "revise/style.css";
|
|
95
|
+
// e.g. Hocuspocus onLoadDocument: safe on every connection
|
|
96
|
+
await seedYDoc(room, "contract.docx");
|
|
18
97
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
console.log(documentId, "now has", document.children.length, "blocks");
|
|
25
|
-
}}
|
|
26
|
-
/>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
98
|
+
const doc = await ReviseDocument.fromYDoc(room, { author: "Review bot" });
|
|
99
|
+
await doc.tools.call("replace", {
|
|
100
|
+
/* ... */
|
|
101
|
+
});
|
|
102
|
+
const { bytes } = await doc.export({ format: "docx" });
|
|
29
103
|
```
|
|
30
104
|
|
|
31
|
-
The editor
|
|
32
|
-
|
|
105
|
+
The browser editor for the same documents is
|
|
106
|
+
[`@reviseio/editor`](https://www.npmjs.com/package/@reviseio/editor).
|
|
107
|
+
|
|
108
|
+
## Docs
|
|
33
109
|
|
|
34
|
-
|
|
110
|
+
- [revise.io/developer/docs](https://revise.io/developer/docs)
|
|
111
|
+
- [Build with AI](https://revise.io/developer/docs/build-with-ai): skills,
|
|
112
|
+
plugins, and Markdown versions of every page
|
|
113
|
+
- [Changelog](https://revise.io/developer/docs/revise/changelog)
|
|
35
114
|
|
|
36
115
|
## License
|
|
37
116
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
commercial
|
|
41
|
-
[developer.revise.io/editor-sdk/license](https://developer.revise.io/editor-sdk/license),
|
|
42
|
-
or email [sdk@revise.io](mailto:sdk@revise.io).
|
|
117
|
+
MIT. `revise` runs on [`@reviseio/engine`](https://www.npmjs.com/package/@reviseio/engine),
|
|
118
|
+
Revise's document engine, which is installed with it and is free for any use,
|
|
119
|
+
including commercial, under its own license.
|
package/agent.d.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revise's editing tools for your own agent loop, in the shape each model
|
|
3
|
+
* API expects: hand `tools` to the model, pass each tool call it makes to
|
|
4
|
+
* `handle`, and send back what `handle` returns.
|
|
5
|
+
*
|
|
6
|
+
* const agent = agentTools(doc, { provider: "anthropic" });
|
|
7
|
+
* const reply = await anthropic.messages.create({ model, tools: agent.tools, messages });
|
|
8
|
+
* const results = await Promise.all(
|
|
9
|
+
* reply.content.filter((b) => b.type === "tool_use").map(agent.handle),
|
|
10
|
+
* );
|
|
11
|
+
* messages.push({ role: "assistant", content: reply.content }, { role: "user", content: results });
|
|
12
|
+
*
|
|
13
|
+
* OpenAI Responses: pass `agent.tools` as `tools`, append every output item
|
|
14
|
+
* the model returned (reasoning and function_call items included) to your
|
|
15
|
+
* input, then the `function_call_output` items `handle` returns, and call
|
|
16
|
+
* again until the model stops calling tools.
|
|
17
|
+
*
|
|
18
|
+
* No model SDK is a dependency: plain objects in, plain objects out. Every
|
|
19
|
+
* call runs on the document's one tool session, so reads, searches, and
|
|
20
|
+
* edits share context across turns, and calls run one at a time (parallel
|
|
21
|
+
* tool calls are safe; they queue). The session remembers what the model
|
|
22
|
+
* has read: when your host compacts or drops the transcript, call
|
|
23
|
+
* `reset()` so it stops assuming the model still has that text. Tool
|
|
24
|
+
* descriptions mention "turns": here a turn is one model response.
|
|
25
|
+
*/
|
|
26
|
+
import type { ReviseToolResult } from "@reviseio/engine";
|
|
27
|
+
import type { ReviseDocument } from "./document.js";
|
|
28
|
+
export type AgentProvider = "anthropic" | "openai" | "openai-responses";
|
|
29
|
+
export interface AgentToolsOptions {
|
|
30
|
+
provider: AgentProvider;
|
|
31
|
+
/** Cap on one tool result's text, in characters (default 100,000). Longer
|
|
32
|
+
* results are cut with a note telling the model how to page. */
|
|
33
|
+
maxResultChars?: number;
|
|
34
|
+
/** Only these tools (by name). */
|
|
35
|
+
include?: string[];
|
|
36
|
+
/** Every tool except these. */
|
|
37
|
+
exclude?: string[];
|
|
38
|
+
}
|
|
39
|
+
/** Anthropic Messages API: a `tool_use` content block. */
|
|
40
|
+
export interface AnthropicToolUse {
|
|
41
|
+
type?: "tool_use";
|
|
42
|
+
id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
input: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** OpenAI Chat Completions: an entry of `message.tool_calls`. */
|
|
47
|
+
export interface OpenAIToolCall {
|
|
48
|
+
id: string;
|
|
49
|
+
type?: "function";
|
|
50
|
+
function: {
|
|
51
|
+
name: string;
|
|
52
|
+
arguments: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** OpenAI Responses API: a `function_call` output item. */
|
|
56
|
+
export interface OpenAIResponsesFunctionCall {
|
|
57
|
+
type?: "function_call";
|
|
58
|
+
call_id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
arguments: string;
|
|
61
|
+
}
|
|
62
|
+
interface ProviderShapes {
|
|
63
|
+
anthropic: {
|
|
64
|
+
tool: {
|
|
65
|
+
name: string;
|
|
66
|
+
description: string;
|
|
67
|
+
input_schema: {
|
|
68
|
+
type: "object";
|
|
69
|
+
[key: string]: unknown;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
call: AnthropicToolUse;
|
|
73
|
+
result: {
|
|
74
|
+
type: "tool_result";
|
|
75
|
+
tool_use_id: string;
|
|
76
|
+
content: string;
|
|
77
|
+
is_error?: boolean;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
openai: {
|
|
81
|
+
tool: {
|
|
82
|
+
type: "function";
|
|
83
|
+
function: {
|
|
84
|
+
name: string;
|
|
85
|
+
description: string;
|
|
86
|
+
parameters: {
|
|
87
|
+
[key: string]: unknown;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
call: OpenAIToolCall;
|
|
92
|
+
result: {
|
|
93
|
+
role: "tool";
|
|
94
|
+
tool_call_id: string;
|
|
95
|
+
content: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
"openai-responses": {
|
|
99
|
+
tool: {
|
|
100
|
+
type: "function";
|
|
101
|
+
name: string;
|
|
102
|
+
description: string;
|
|
103
|
+
parameters: {
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
};
|
|
106
|
+
/** Revise's schemas use optional fields, which strict mode rejects. */
|
|
107
|
+
strict: false;
|
|
108
|
+
};
|
|
109
|
+
call: OpenAIResponsesFunctionCall;
|
|
110
|
+
result: {
|
|
111
|
+
type: "function_call_output";
|
|
112
|
+
call_id: string;
|
|
113
|
+
output: string;
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
export interface AgentTools<P extends AgentProvider> {
|
|
118
|
+
/** Tool definitions in the provider's format. */
|
|
119
|
+
tools: Array<ProviderShapes[P]["tool"]>;
|
|
120
|
+
/** Run one tool call; returns the provider's tool-result message. Never
|
|
121
|
+
* throws for a bad call: the model gets the error to correct itself. */
|
|
122
|
+
handle: (call: ProviderShapes[P]["call"]) => Promise<ProviderShapes[P]["result"]>;
|
|
123
|
+
/** Did the last handled calls change the document? Compare to decide
|
|
124
|
+
* whether to save. */
|
|
125
|
+
version: () => Uint8Array;
|
|
126
|
+
/** Forget what the model has read (after compacting its transcript). */
|
|
127
|
+
reset: () => Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
/** A tool result as the text a model reads: the message, any tracked
|
|
130
|
+
* change ids, the document HTML it loaded, and its structured data (counts,
|
|
131
|
+
* paging, what changed), within a size budget. */
|
|
132
|
+
export declare function formatToolResult(result: ReviseToolResult<string>, maxChars?: number): {
|
|
133
|
+
text: string;
|
|
134
|
+
isError: boolean;
|
|
135
|
+
};
|
|
136
|
+
export declare function agentTools<P extends AgentProvider>(doc: ReviseDocument, options: AgentToolsOptions & {
|
|
137
|
+
provider: P;
|
|
138
|
+
}): AgentTools<P>;
|
|
139
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// revise: MIT License. https://revise.io/developer/docs
|
|
2
|
+
import {
|
|
3
|
+
ReviseError
|
|
4
|
+
} from "./chunk-U6YKQBKL.js";
|
|
5
|
+
|
|
6
|
+
// src/embed-sdk/lib/package.ts
|
|
7
|
+
import { engineModules } from "@reviseio/engine";
|
|
8
|
+
import JSZip from "jszip";
|
|
9
|
+
import { installDomShims } from "@reviseio/engine";
|
|
10
|
+
async function listParts(bytes) {
|
|
11
|
+
const zip = await JSZip.loadAsync(bytes);
|
|
12
|
+
const parts = [];
|
|
13
|
+
for (const [path, entry] of Object.entries(zip.files)) {
|
|
14
|
+
if (entry.dir) continue;
|
|
15
|
+
parts.push({ path, bytes: (await entry.async("uint8array")).length });
|
|
16
|
+
}
|
|
17
|
+
return parts.sort((a, b) => a.path.localeCompare(b.path));
|
|
18
|
+
}
|
|
19
|
+
async function readPart(zip, part) {
|
|
20
|
+
const file = zip.file(part);
|
|
21
|
+
if (!file) {
|
|
22
|
+
throw new ReviseError(`No part "${part}" in this document.`, "no_such_part");
|
|
23
|
+
}
|
|
24
|
+
return file.async("string");
|
|
25
|
+
}
|
|
26
|
+
var UNITS = [
|
|
27
|
+
"w:rPr",
|
|
28
|
+
"w:pPr",
|
|
29
|
+
"w:p",
|
|
30
|
+
"w:tr",
|
|
31
|
+
"w:style",
|
|
32
|
+
"w:abstractNum",
|
|
33
|
+
"w:num",
|
|
34
|
+
"w:lvl",
|
|
35
|
+
"w:sectPr",
|
|
36
|
+
"w:tbl"
|
|
37
|
+
];
|
|
38
|
+
var CAT_MATCH_LIMIT = 20;
|
|
39
|
+
async function catPart(bytes, part, match, limit = CAT_MATCH_LIMIT) {
|
|
40
|
+
const xml = await readPart(await JSZip.loadAsync(bytes), part);
|
|
41
|
+
if (!match) return [xml];
|
|
42
|
+
const found = /* @__PURE__ */ new Set();
|
|
43
|
+
let at = xml.indexOf(match);
|
|
44
|
+
while (at >= 0 && found.size < limit) {
|
|
45
|
+
let best;
|
|
46
|
+
for (const tag of UNITS) {
|
|
47
|
+
const start = Math.max(
|
|
48
|
+
xml.lastIndexOf(`<${tag} `, at),
|
|
49
|
+
xml.lastIndexOf(`<${tag}>`, at)
|
|
50
|
+
);
|
|
51
|
+
if (start < 0) continue;
|
|
52
|
+
const close = xml.indexOf(`</${tag}>`, start);
|
|
53
|
+
if (close < 0 || close < at) continue;
|
|
54
|
+
const unit = xml.slice(start, close + tag.length + 3);
|
|
55
|
+
if (!best || unit.length < best.length) best = unit;
|
|
56
|
+
}
|
|
57
|
+
found.add(
|
|
58
|
+
best ?? xml.slice(Math.max(0, at - 200), at + match.length + 200)
|
|
59
|
+
);
|
|
60
|
+
at = xml.indexOf(match, at + match.length);
|
|
61
|
+
}
|
|
62
|
+
return [...found];
|
|
63
|
+
}
|
|
64
|
+
var MODEL_READ_PARTS = /^word\/(document|styles|numbering|footnotes|endnotes|comments|header\d*|footer\d*)\.xml$/;
|
|
65
|
+
async function assertWellFormed(part, xml) {
|
|
66
|
+
await installDomShims();
|
|
67
|
+
const parsed = new DOMParser().parseFromString(xml, "application/xml");
|
|
68
|
+
const error = parsed.getElementsByTagName("parsererror")[0];
|
|
69
|
+
if (error) {
|
|
70
|
+
throw new ReviseError(
|
|
71
|
+
`The patched ${part} is not well-formed XML: ${error.textContent?.trim().split("\n")[0] ?? "parse error"}. Nothing was changed.`,
|
|
72
|
+
"malformed_xml"
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function patchPackage(pkg, request, readFile) {
|
|
77
|
+
const zip = await JSZip.loadAsync(pkg);
|
|
78
|
+
const before = await readPart(zip, request.part);
|
|
79
|
+
let after;
|
|
80
|
+
let replacements = 0;
|
|
81
|
+
if (request.file !== void 0) {
|
|
82
|
+
after = readFile(request.file);
|
|
83
|
+
replacements = 1;
|
|
84
|
+
} else {
|
|
85
|
+
if (!request.find) {
|
|
86
|
+
throw new ReviseError(
|
|
87
|
+
"Give --find and --replace, or --file to replace the whole part.",
|
|
88
|
+
"usage"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
const occurrences = before.split(request.find).length - 1;
|
|
92
|
+
if (occurrences === 0) {
|
|
93
|
+
throw new ReviseError(
|
|
94
|
+
`"${request.find}" does not occur in ${request.part}.`,
|
|
95
|
+
"find_not_found"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (occurrences > 1 && !request.all) {
|
|
99
|
+
throw new ReviseError(
|
|
100
|
+
`"${request.find}" occurs ${occurrences} times in ${request.part}; add context to match once, or pass --all.`,
|
|
101
|
+
"find_ambiguous"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
after = before.split(request.find).join(request.replace ?? "");
|
|
105
|
+
replacements = request.all ? occurrences : 1;
|
|
106
|
+
}
|
|
107
|
+
await assertWellFormed(request.part, after);
|
|
108
|
+
if (request.part === "word/document.xml") {
|
|
109
|
+
const { scanElementChildren } = await engineModules.xmlScan();
|
|
110
|
+
const shape = (xml) => scanElementChildren(xml, "w:body").children.map((child) => child.tag).join(",");
|
|
111
|
+
if (shape(before) !== shape(after)) {
|
|
112
|
+
throw new ReviseError(
|
|
113
|
+
"This patch adds, removes, or reorders body elements, which a direct patch cannot do. Use the editing tools for body structure. Nothing was changed.",
|
|
114
|
+
"body_shape_changed"
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
zip.file(request.part, after);
|
|
119
|
+
const bytes = await zip.generateAsync({
|
|
120
|
+
type: "uint8array",
|
|
121
|
+
compression: "DEFLATE"
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
bytes,
|
|
125
|
+
replacements,
|
|
126
|
+
modelRead: MODEL_READ_PARTS.test(request.part)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
listParts,
|
|
132
|
+
CAT_MATCH_LIMIT,
|
|
133
|
+
catPart,
|
|
134
|
+
patchPackage
|
|
135
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// revise: MIT License. https://revise.io/developer/docs
|
|
2
|
+
|
|
3
|
+
// src/embed-sdk/lib/errors.ts
|
|
4
|
+
var ReviseError = class extends Error {
|
|
5
|
+
constructor(message, code = "error", options = {}) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.name = "ReviseError";
|
|
9
|
+
if (options.cause !== void 0) this.cause = options.cause;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
ReviseError
|
|
15
|
+
};
|