superdoc-sdk 1.0.0__tar.gz

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 (35) hide show
  1. superdoc_sdk-1.0.0/PKG-INFO +407 -0
  2. superdoc_sdk-1.0.0/README.md +393 -0
  3. superdoc_sdk-1.0.0/pyproject.toml +33 -0
  4. superdoc_sdk-1.0.0/setup.cfg +4 -0
  5. superdoc_sdk-1.0.0/superdoc/__init__.py +28 -0
  6. superdoc_sdk-1.0.0/superdoc/client.py +424 -0
  7. superdoc_sdk-1.0.0/superdoc/embedded_cli.py +113 -0
  8. superdoc_sdk-1.0.0/superdoc/errors.py +19 -0
  9. superdoc_sdk-1.0.0/superdoc/generated/__init__.py +2 -0
  10. superdoc_sdk-1.0.0/superdoc/generated/client.py +55952 -0
  11. superdoc_sdk-1.0.0/superdoc/generated/contract.py +7 -0
  12. superdoc_sdk-1.0.0/superdoc/protocol.py +312 -0
  13. superdoc_sdk-1.0.0/superdoc/runtime.py +119 -0
  14. superdoc_sdk-1.0.0/superdoc/skill_api.py +154 -0
  15. superdoc_sdk-1.0.0/superdoc/skills/__init__.py +1 -0
  16. superdoc_sdk-1.0.0/superdoc/skills/editing-docx.md +31 -0
  17. superdoc_sdk-1.0.0/superdoc/test_parity_helper.py +76 -0
  18. superdoc_sdk-1.0.0/superdoc/tools/catalog.json +3913 -0
  19. superdoc_sdk-1.0.0/superdoc/tools/intent_dispatch_generated.py +122 -0
  20. superdoc_sdk-1.0.0/superdoc/tools/tools-policy.json +43 -0
  21. superdoc_sdk-1.0.0/superdoc/tools/tools.anthropic.json +3621 -0
  22. superdoc_sdk-1.0.0/superdoc/tools/tools.generic.json +3710 -0
  23. superdoc_sdk-1.0.0/superdoc/tools/tools.openai.json +3648 -0
  24. superdoc_sdk-1.0.0/superdoc/tools/tools.vercel.json +3648 -0
  25. superdoc_sdk-1.0.0/superdoc/tools_api.py +209 -0
  26. superdoc_sdk-1.0.0/superdoc/transport.py +725 -0
  27. superdoc_sdk-1.0.0/superdoc_sdk.egg-info/PKG-INFO +407 -0
  28. superdoc_sdk-1.0.0/superdoc_sdk.egg-info/SOURCES.txt +33 -0
  29. superdoc_sdk-1.0.0/superdoc_sdk.egg-info/dependency_links.txt +1 -0
  30. superdoc_sdk-1.0.0/superdoc_sdk.egg-info/requires.txt +15 -0
  31. superdoc_sdk-1.0.0/superdoc_sdk.egg-info/top_level.txt +1 -0
  32. superdoc_sdk-1.0.0/tests/test_client_method_naming.py +124 -0
  33. superdoc_sdk-1.0.0/tests/test_helpers_reexports.py +57 -0
  34. superdoc_sdk-1.0.0/tests/test_protocol.py +449 -0
  35. superdoc_sdk-1.0.0/tests/test_transport.py +495 -0
@@ -0,0 +1,407 @@
1
+ Metadata-Version: 2.4
2
+ Name: superdoc-sdk
3
+ Version: 1.0.0
4
+ Summary: SuperDoc SDK (CLI-backed)
5
+ Author: SuperDoc
6
+ License-Expression: AGPL-3.0
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: superdoc-sdk-cli-darwin-arm64==1.0.0; platform_system == "Darwin" and (platform_machine == "arm64" or platform_machine == "aarch64" or platform_machine == "ARM64")
10
+ Requires-Dist: superdoc-sdk-cli-darwin-x64==1.0.0; platform_system == "Darwin" and (platform_machine == "x86_64" or platform_machine == "AMD64" or platform_machine == "amd64")
11
+ Requires-Dist: superdoc-sdk-cli-linux-x64==1.0.0; platform_system == "Linux" and (platform_machine == "x86_64" or platform_machine == "AMD64" or platform_machine == "amd64")
12
+ Requires-Dist: superdoc-sdk-cli-linux-arm64==1.0.0; platform_system == "Linux" and (platform_machine == "arm64" or platform_machine == "aarch64" or platform_machine == "ARM64")
13
+ Requires-Dist: superdoc-sdk-cli-windows-x64==1.0.0; platform_system == "Windows" and (platform_machine == "x86_64" or platform_machine == "AMD64" or platform_machine == "amd64")
14
+
15
+ # superdoc-sdk
16
+
17
+ Programmatic SDK for deterministic DOCX operations through SuperDoc's Document API.
18
+
19
+ > **Alpha** — The API surface matches the [Document API](https://docs.superdoc.dev/document-api/overview) and will evolve alongside it.
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ pip install superdoc-sdk
25
+ ```
26
+
27
+ The CLI is bundled with the SDK — no separate install needed. A platform-specific CLI companion package is installed automatically via [PEP 508 environment markers](https://peps.python.org/pep-0508/).
28
+
29
+ | Platform | Architecture |
30
+ |----------|-------------|
31
+ | macOS | Apple Silicon (arm64), Intel (x64) |
32
+ | Linux | x64, ARM64 |
33
+ | Windows | x64 |
34
+
35
+ ## Quick start
36
+
37
+ ```python
38
+ import asyncio
39
+
40
+ from superdoc import AsyncSuperDocClient
41
+
42
+
43
+ async def main():
44
+ async with AsyncSuperDocClient(default_change_mode="tracked") as client:
45
+ # Open a document
46
+ doc = await client.open({"doc": "./contract.docx"})
47
+
48
+ # Find and replace text with query + mutation plan
49
+ match = await doc.query.match(
50
+ {
51
+ "select": {"type": "text", "pattern": "ACME Corp"},
52
+ "require": "first",
53
+ }
54
+ )
55
+
56
+ items = match.get("items") or []
57
+ first_item = items[0] if items else {}
58
+ ref = first_item.get("handle", {}).get("ref")
59
+ if ref:
60
+ await doc.mutations.apply(
61
+ {
62
+ "expectedRevision": match["evaluatedRevision"],
63
+ "atomic": True,
64
+ "steps": [
65
+ {
66
+ "id": "replace-acme",
67
+ "op": "text.rewrite",
68
+ "where": {"by": "ref", "ref": ref},
69
+ "args": {"replacement": {"text": "NewCo Inc."}},
70
+ }
71
+ ],
72
+ }
73
+ )
74
+
75
+ # Save and close
76
+ await doc.save({"inPlace": True})
77
+ await doc.close({})
78
+
79
+
80
+ asyncio.run(main())
81
+ ```
82
+
83
+ Set `default_change_mode="tracked"` to make mutations use tracked changes by default. If you pass `changeMode` on a specific call, that explicit value overrides the default.
84
+
85
+ The SDK also exposes a synchronous `SuperDocClient` with the same document-handle methods when you prefer non-async code paths.
86
+
87
+ ### Sync
88
+
89
+ ```python
90
+ from superdoc import SuperDocClient
91
+
92
+ with SuperDocClient() as client:
93
+ doc = client.open({"doc": "./contract.docx"})
94
+
95
+ info = doc.info({})
96
+ print(info["counts"])
97
+
98
+ doc.save({"inPlace": True})
99
+ doc.close({})
100
+ ```
101
+
102
+ ## User identity
103
+
104
+ By default the SDK attributes edits to a generic "CLI" user. Set `user` on the client to identify your automation in comments, tracked changes, and collaboration presence:
105
+
106
+ ```python
107
+ client = AsyncSuperDocClient(user={"name": "Review Bot", "email": "bot@example.com"})
108
+ ```
109
+
110
+ The `user` is injected into every `client.open` call. If you pass `userName` or `userEmail` on a specific `client.open`, those per-call values take precedence.
111
+
112
+ ## Client lifecycle
113
+
114
+ The SDK uses a persistent host process for all operations. The host is started on first use and reused across calls, avoiding per-operation subprocess overhead.
115
+
116
+ ### Context managers (recommended)
117
+
118
+ ```python
119
+ # Sync
120
+ with SuperDocClient() as client:
121
+ doc = client.open({"doc": "./test.docx"})
122
+ doc.find({"query": "test"})
123
+
124
+ # Async
125
+ async with AsyncSuperDocClient() as client:
126
+ doc = await client.open({"doc": "./test.docx"})
127
+ await doc.find({"query": "test"})
128
+ ```
129
+
130
+ The context manager calls `connect()` on entry and `dispose()` on exit (including on exception).
131
+
132
+ ### Explicit lifecycle
133
+
134
+ ```python
135
+ client = SuperDocClient()
136
+ client.connect() # Optional — first invoke() auto-connects
137
+ doc = client.open({"doc": "./test.docx"})
138
+ result = doc.find({"query": "test"})
139
+ client.dispose() # Shuts down the host process
140
+ ```
141
+
142
+ `connect()` is optional. If not called explicitly, the first operation triggers a lazy connection to the host process.
143
+
144
+ ### Configuration
145
+
146
+ ```python
147
+ client = SuperDocClient(
148
+ startup_timeout_ms=10_000, # Max time for host handshake (default: 5000)
149
+ shutdown_timeout_ms=5_000, # Max time for graceful shutdown (default: 5000)
150
+ request_timeout_ms=60_000, # Per-operation timeout passed to CLI (default: None)
151
+ watchdog_timeout_ms=30_000, # Client-side safety timer per request (default: 30000)
152
+ default_change_mode="tracked", # Auto-inject changeMode for mutations (default: None)
153
+ user={"name": "Bot", "email": "bot@example.com"}, # User identity for attribution
154
+ env={"SUPERDOC_CLI_BIN": "/path/to/superdoc"}, # Environment overrides
155
+ )
156
+ ```
157
+
158
+ ### Thread safety
159
+
160
+ Client instances are serialized: one operation at a time per client. For parallelism, use multiple client instances. Do not share a single client across threads.
161
+
162
+ ## Collaboration sessions
163
+
164
+ Use this when your app already has a live collaboration room (Liveblocks, Hocuspocus, or SuperDoc Yjs).
165
+
166
+ ### Join an existing room
167
+
168
+ Pass `collabUrl` and `collabDocumentId` to `client.open`:
169
+
170
+ ```python
171
+ import asyncio
172
+
173
+ from superdoc import AsyncSuperDocClient
174
+
175
+
176
+ async def main():
177
+ async with AsyncSuperDocClient() as client:
178
+ doc = await client.open({
179
+ "collabUrl": "ws://localhost:4000",
180
+ "collabDocumentId": "my-doc-room",
181
+ })
182
+
183
+ await doc.insert({
184
+ "target": {"type": "end"},
185
+ "content": "Added by the SDK",
186
+ })
187
+
188
+
189
+ asyncio.run(main())
190
+ ```
191
+
192
+ ### Start an empty room from a local `.docx`
193
+
194
+ If the room is empty, pass `doc` together with collaboration params:
195
+
196
+ ```python
197
+ doc = await client.open({
198
+ "doc": "./starting-template.docx",
199
+ "collabUrl": "ws://localhost:4000",
200
+ "collabDocumentId": "my-doc-room",
201
+ })
202
+ ```
203
+
204
+ What happens when you pass `doc`:
205
+
206
+ | Room state | Result |
207
+ | --- | --- |
208
+ | Room already has content | SDK joins the room. `doc` is ignored. |
209
+ | Room is empty and `doc` is provided | SDK seeds the room from `doc`, then joins. |
210
+ | Room is empty and no `doc` is provided | SDK starts a blank document. |
211
+
212
+ ### Control empty-room behavior
213
+
214
+ | Parameter | Type | Default | Description |
215
+ | --- | --- | --- | --- |
216
+ | `collabUrl` | `string` | — | WebSocket URL for your collaboration provider. |
217
+ | `collabDocumentId` | `string` | session ID | Room/document ID on the provider. |
218
+ | `doc` | `string` | — | Local `.docx` used only when the room is empty. |
219
+ | `onMissing` | `string` | `seedFromDoc` | `seedFromDoc`, `blank`, or `error`. |
220
+ | `bootstrapSettlingMs` | `number` | `1500` | Wait time (ms) before seeding to avoid race conditions. |
221
+
222
+ If you only want to join rooms that already exist, use `onMissing: 'error'`:
223
+
224
+ ```python
225
+ doc = await client.open({
226
+ "collabUrl": "ws://localhost:4000",
227
+ "collabDocumentId": "my-doc-room",
228
+ "onMissing": "error",
229
+ })
230
+ ```
231
+
232
+ ### Check if the SDK seeded or joined
233
+
234
+ `client.open` returns a bound document handle. In collaboration mode, bootstrap details are available on `doc.open_result`:
235
+
236
+ ```python
237
+ doc = await client.open({
238
+ "doc": "./starting-template.docx",
239
+ "collabUrl": "ws://localhost:4000",
240
+ "collabDocumentId": "my-doc-room",
241
+ })
242
+
243
+ print(doc.open_result.get("bootstrap"))
244
+ # { roomState, bootstrapApplied, bootstrapSource }
245
+ ```
246
+
247
+ ## Available operations
248
+
249
+ The SDK exposes all document-handle operations from the [Document API](https://docs.superdoc.dev/document-api/overview) plus client lifecycle and introspection methods.
250
+
251
+ ### Lifecycle
252
+
253
+ | Operation | Description |
254
+ | --- | --- |
255
+ | `client.open` | Open a document and return a bound document handle. Optionally override the document body with contentOverride + overrideType (markdown, html, or text). |
256
+ | `doc.save` | Save the current session to the original file or a new path. |
257
+ | `doc.close` | Close the bound editing session and clean up resources. |
258
+
259
+ ### Query
260
+
261
+ | Operation | Description |
262
+ | --- | --- |
263
+ | `doc.find` | Search the document for nodes matching type, text, or attribute criteria. |
264
+ | `doc.get_node` | Retrieve a single node by target position. |
265
+ | `doc.get_node_by_id` | Retrieve a single node by its unique ID. |
266
+ | `doc.get_text` | Extract the plain-text content of the document. |
267
+ | `doc.get_markdown` | Extract the document content as a Markdown string. |
268
+ | `doc.info` | Return document metadata including revision, node count, and capabilities. |
269
+ | `doc.query.match` | Deterministic selector-based search with cardinality contracts for mutation targeting. |
270
+ | `doc.mutations.preview` | Dry-run a mutation plan, returning resolved targets without applying changes. |
271
+
272
+ ### Mutation
273
+
274
+ | Operation | Description |
275
+ | --- | --- |
276
+ | `doc.insert` | Insert content at a target position, or at the end of the document when target is omitted. Supports text (default), markdown, and html content types via the `type` field. |
277
+ | `doc.replace` | Replace content at a target position with new text or inline content. |
278
+ | `doc.delete` | Delete content at a target position. |
279
+ | `doc.mutations.apply` | Execute a mutation plan atomically against the document. |
280
+
281
+ ### Format
282
+
283
+ | Operation | Description |
284
+ | --- | --- |
285
+ | `doc.format.apply` | Apply inline run-property patch changes to the target range with explicit set/clear semantics. |
286
+ | `doc.format.bold` | Set or clear bold on the target text range. |
287
+ | `doc.format.italic` | Set or clear italic on the target text range. |
288
+ | `doc.format.strike` | Set or clear strikethrough on the target text range. |
289
+ | `doc.format.underline` | Set or clear underline on the target text range. |
290
+ | `doc.format.highlight` | Set or clear highlight on the target text range. |
291
+ | `doc.format.color` | Set or clear text color on the target text range. |
292
+ | `doc.format.font_size` | Set or clear font size on the target text range. |
293
+ | `doc.format.font_family` | Set or clear font family on the target text range. |
294
+
295
+ And 30+ additional formatting operations (letter spacing, vertical alignment, small caps, shading, borders, and more).
296
+
297
+ ### Create
298
+
299
+ | Operation | Description |
300
+ | --- | --- |
301
+ | `doc.create.paragraph` | Create a new paragraph at the target position. |
302
+ | `doc.create.heading` | Create a new heading at the target position. |
303
+ | `doc.create.section_break` | Create a section break at the target location. |
304
+ | `doc.create.table` | Create a new table at the target position. |
305
+ | `doc.create.table_of_contents` | Insert a new table of contents at the target position. |
306
+
307
+ ### Blocks
308
+
309
+ | Operation | Description |
310
+ | --- | --- |
311
+ | `doc.blocks.delete` | Delete an entire block node (paragraph, heading, list item, table, image, or sdt). |
312
+
313
+ ### Lists
314
+
315
+ | Operation | Description |
316
+ | --- | --- |
317
+ | `doc.lists.list` | List all list nodes in the document, optionally filtered by scope. |
318
+ | `doc.lists.get` | Retrieve a specific list node by target. |
319
+ | `doc.lists.insert` | Insert a new list at the target position. |
320
+ | `doc.lists.create` | Create a new list from one or more paragraphs. |
321
+ | `doc.lists.attach` | Convert non-list paragraphs to list items under an existing list sequence. |
322
+ | `doc.lists.detach` | Remove numbering properties from list items, converting them to plain paragraphs. |
323
+ | `doc.lists.indent` | Increase the indentation level of a list item. |
324
+ | `doc.lists.outdent` | Decrease the indentation level of a list item. |
325
+ | `doc.lists.join` | Merge two adjacent list sequences into one. |
326
+ | `doc.lists.can_join` | Check whether two adjacent list sequences can be joined. |
327
+ | `doc.lists.separate` | Split a list sequence at the target item. |
328
+ | `doc.lists.set_level` | Set the absolute nesting level (0..8) of a list item. |
329
+ | `doc.lists.set_value` | Set an explicit numbering value at the target item. |
330
+ | `doc.lists.continue_previous` | Continue numbering from the nearest compatible previous list sequence. |
331
+ | `doc.lists.can_continue_previous` | Check whether the target sequence can continue numbering from a previous sequence. |
332
+ | `doc.lists.set_level_restart` | Set the restart behavior for a specific list level. |
333
+ | `doc.lists.convert_to_text` | Convert list items to plain paragraphs, optionally prepending the rendered marker text. |
334
+
335
+ ### Comments
336
+
337
+ | Operation | Description |
338
+ | --- | --- |
339
+ | `doc.comments.create` | Create a new comment thread (or reply when parentCommentId is given). |
340
+ | `doc.comments.patch` | Patch fields on an existing comment (text, target, status, or isInternal). |
341
+ | `doc.comments.delete` | Remove a comment or reply by ID. |
342
+ | `doc.comments.get` | Retrieve a single comment thread by ID. |
343
+ | `doc.comments.list` | List all comment threads in the document. |
344
+
345
+ ### Track changes
346
+
347
+ | Operation | Description |
348
+ | --- | --- |
349
+ | `doc.track_changes.list` | List all tracked changes in the document. |
350
+ | `doc.track_changes.get` | Retrieve a single tracked change by ID. |
351
+ | `doc.track_changes.decide` | Accept or reject a tracked change (by ID or scope: all). |
352
+
353
+ ### History
354
+
355
+ | Operation | Description |
356
+ | --- | --- |
357
+ | `doc.history.get` | Query the current undo/redo history state of the active editor. |
358
+ | `doc.history.undo` | Undo the most recent history-safe mutation in the active editor. |
359
+ | `doc.history.redo` | Redo the most recently undone action in the active editor. |
360
+
361
+ ### Client methods
362
+
363
+ | Operation | Description |
364
+ | --- | --- |
365
+ | `client.describe` | List all available CLI operations and contract metadata. |
366
+ | `client.describe_command` | Show detailed metadata for a single CLI operation. |
367
+
368
+ ## Troubleshooting
369
+
370
+ ### Custom CLI binary
371
+
372
+ If you need to use a custom-built CLI binary (e.g. a newer version or a patched build), set the `SUPERDOC_CLI_BIN` environment variable:
373
+
374
+ ```bash
375
+ export SUPERDOC_CLI_BIN=/path/to/superdoc
376
+ ```
377
+
378
+ ### Debug logging
379
+
380
+ Enable transport-level debug logging to diagnose connectivity issues:
381
+
382
+ ```bash
383
+ export SUPERDOC_DEBUG=1
384
+ ```
385
+
386
+ ### Air-gapped / private index environments
387
+
388
+ Mirror both `superdoc-sdk` and the `superdoc-sdk-cli-*` package for your platform to your private index. For example, on macOS ARM64:
389
+
390
+ ```bash
391
+ pip download superdoc-sdk superdoc-sdk-cli-darwin-arm64
392
+ # Upload both wheels to your private index
393
+ ```
394
+
395
+ ## Related
396
+
397
+ - [Document API](https://docs.superdoc.dev/document-api/overview) — the in-browser API that defines the operation set
398
+ - [CLI](https://docs.superdoc.dev/document-engine/cli) — use the same operations from the terminal
399
+ - [Collaboration guides](https://docs.superdoc.dev/modules/collaboration/overview) — set up Liveblocks, Hocuspocus, or SuperDoc Yjs
400
+
401
+ ## Part of SuperDoc
402
+
403
+ This SDK is part of [SuperDoc](https://github.com/superdoc-dev/superdoc) — an open source document editor bringing Microsoft Word to the web.
404
+
405
+ ## License
406
+
407
+ AGPL-3.0 · [Enterprise license available](https://superdoc.dev)