@superdoc/mcp 1.2.0-next.1 → 1.2.0-next.10
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/dist/index.js +374 -84
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -31314,7 +31314,7 @@ var init_host = __esm(() => {
|
|
|
31314
31314
|
});
|
|
31315
31315
|
|
|
31316
31316
|
// ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
|
|
31317
|
-
var SDK_VERSION = "2.15.0-next.
|
|
31317
|
+
var SDK_VERSION = "2.15.0-next.10";
|
|
31318
31318
|
|
|
31319
31319
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31320
31320
|
import { chmodSync, existsSync } from "node:fs";
|
|
@@ -31891,7 +31891,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
31891
31891
|
"tools": [
|
|
31892
31892
|
{
|
|
31893
31893
|
"toolName": "superdoc_get_content",
|
|
31894
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
31894
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
31895
31895
|
"inputSchema": {
|
|
31896
31896
|
"type": "object",
|
|
31897
31897
|
"properties": {
|
|
@@ -38169,7 +38169,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
38169
38169
|
},
|
|
38170
38170
|
{
|
|
38171
38171
|
"toolName": "superdoc_mutations",
|
|
38172
|
-
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
38172
|
+
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:\\"select\\" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
38173
38173
|
"inputSchema": {
|
|
38174
38174
|
"type": "object",
|
|
38175
38175
|
"properties": {
|
|
@@ -42255,7 +42255,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
42255
42255
|
"type": "function",
|
|
42256
42256
|
"function": {
|
|
42257
42257
|
"name": "superdoc_get_content",
|
|
42258
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
42258
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
42259
42259
|
"parameters": {
|
|
42260
42260
|
"type": "object",
|
|
42261
42261
|
"properties": {
|
|
@@ -48137,7 +48137,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
48137
48137
|
"type": "function",
|
|
48138
48138
|
"function": {
|
|
48139
48139
|
"name": "superdoc_mutations",
|
|
48140
|
-
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
48140
|
+
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:\\"select\\" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
48141
48141
|
"parameters": {
|
|
48142
48142
|
"type": "object",
|
|
48143
48143
|
"properties": {
|
|
@@ -51875,7 +51875,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
51875
51875
|
"tools": [
|
|
51876
51876
|
{
|
|
51877
51877
|
"name": "superdoc_get_content",
|
|
51878
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
51878
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
51879
51879
|
"input_schema": {
|
|
51880
51880
|
"type": "object",
|
|
51881
51881
|
"properties": {
|
|
@@ -57733,7 +57733,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
57733
57733
|
},
|
|
57734
57734
|
{
|
|
57735
57735
|
"name": "superdoc_mutations",
|
|
57736
|
-
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
57736
|
+
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:\\"select\\" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
57737
57737
|
"input_schema": {
|
|
57738
57738
|
"type": "object",
|
|
57739
57739
|
"properties": {
|
|
@@ -61469,7 +61469,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
61469
61469
|
"type": "function",
|
|
61470
61470
|
"function": {
|
|
61471
61471
|
"name": "superdoc_get_content",
|
|
61472
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
61472
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
61473
61473
|
"parameters": {
|
|
61474
61474
|
"type": "object",
|
|
61475
61475
|
"properties": {
|
|
@@ -67351,7 +67351,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
67351
67351
|
"type": "function",
|
|
67352
67352
|
"function": {
|
|
67353
67353
|
"name": "superdoc_mutations",
|
|
67354
|
-
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
67354
|
+
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:\\"select\\" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
67355
67355
|
"parameters": {
|
|
67356
67356
|
"type": "object",
|
|
67357
67357
|
"properties": {
|
|
@@ -71089,7 +71089,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
71089
71089
|
"tools": [
|
|
71090
71090
|
{
|
|
71091
71091
|
"name": "superdoc_get_content",
|
|
71092
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
71092
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \\"blocks\\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \\"blocks\\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \\"text\\", \\"markdown\\", and \\"html\\" return compact strings. Actions \\"markdown_projection\\" and \\"html_projection\\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \\"info\\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \\"blocks\\" action supports pagination via \\"offset\\" and \\"limit\\", filtering via \\"nodeTypes\\", and numbering projection via \\"reviewMode\\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"blocks\\"}\\n 2. {\\"action\\":\\"blocks\\",\\"includeText\\":true,\\"offset\\":0,\\"limit\\":20,\\"reviewMode\\":\\"final\\"}\\n 3. {\\"action\\":\\"blocks\\",\\"offset\\":0,\\"limit\\":20,\\"nodeTypes\\":[\\"heading\\",\\"paragraph\\"]}\\n 4. {\\"action\\":\\"text\\"}\\n 5. {\\"action\\":\\"info\\"}\\n 6. {\\"action\\":\\"html_projection\\",\\"reviewMode\\":\\"redline\\",\\"includeSourceMap\\":true}\\n 7. {\\"action\\":\\"markdown_projection\\",\\"reviewMode\\":\\"original\\",\\"scope\\":{\\"kind\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"paragraph-id\\"},\\"includeSourceMap\\":true}",
|
|
71093
71093
|
"parameters": {
|
|
71094
71094
|
"type": "object",
|
|
71095
71095
|
"properties": {
|
|
@@ -77115,7 +77115,7 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
77115
77115
|
},
|
|
77116
77116
|
{
|
|
77117
77117
|
"name": "superdoc_mutations",
|
|
77118
|
-
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
77118
|
+
"description": "All steps succeed or all fail; no partial application. Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. Each step has an id, an op, a \\"where\\" clause for targeting ({by:\\"select\\", select:{...}, require:\\"first\\"|\\"exactlyOne\\"|\\"all\\"} or {by:\\"ref\\", ref:\\"...\\"} or {by:\\"block\\", nodeType:\\"paragraph\\", nodeId:\\"...\\"}), and \\"args\\" with operation-specific parameters. Use {by:\\"block\\", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action \\"blocks\\" without relying on text matching. For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:\\"blocks\\" and includeText:true, then rewrite the matching block by nodeId. For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:\\"select\\" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. Use {by:\\"select\\"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. For create steps, \\"where\\" targets an existing anchor block and args.position (\\"before\\" or \\"after\\") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. For format.apply with require \\"all\\", use a node selector to format every heading or paragraph at once: {by:\\"select\\", select:{type:\\"node\\", nodeType:\\"heading\\"}, require:\\"all\\"}. Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. Action \\"preview\\" dry-runs the plan. Action \\"apply\\" executes it. If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.\\n\\nEXAMPLES:\\n 1. {\\"action\\":\\"apply\\",\\"atomic\\":true,\\"changeMode\\":\\"direct\\",\\"steps\\":[{\\"id\\":\\"s1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"old term\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"new term\\"}}},{\\"id\\":\\"s2\\",\\"op\\":\\"text.delete\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\" (deprecated)\\"},\\"require\\":\\"all\\"},\\"args\\":{}}]}\\n 2. {\\"action\\":\\"apply\\",\\"steps\\":[{\\"id\\":\\"r1\\",\\"op\\":\\"text.rewrite\\",\\"where\\":{\\"by\\":\\"block\\",\\"nodeType\\":\\"paragraph\\",\\"nodeId\\":\\"<nodeId>\\"},\\"args\\":{\\"replacement\\":{\\"text\\":\\"Updated clause text.\\"}}},{\\"id\\":\\"f1\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"node\\",\\"nodeType\\":\\"heading\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"color\\":\\"#FF0000\\"}}},{\\"id\\":\\"f2\\",\\"op\\":\\"format.apply\\",\\"where\\":{\\"by\\":\\"select\\",\\"select\\":{\\"type\\":\\"text\\",\\"pattern\\":\\"Confidential Information\\"},\\"require\\":\\"all\\"},\\"args\\":{\\"inline\\":{\\"bold\\":true}}}]}",
|
|
77119
77119
|
"parameters": {
|
|
77120
77120
|
"type": "object",
|
|
77121
77121
|
"properties": {
|
|
@@ -80918,13 +80918,13 @@ var init_embedded_tools_generated = __esm(() => {
|
|
|
80918
80918
|
|
|
80919
80919
|
Every editing tool needs a **target** telling the API *where* to apply the change. There are three ways to get one:
|
|
80920
80920
|
|
|
80921
|
-
- **From blocks data**: Each block has a \`ref\` (pass directly to superdoc_edit or superdoc_format), a \`nodeId\` (for building \`at\` positions with superdoc_create or \`where: {by: "block", ...}\` in superdoc_mutations), and optional full \`text\` when you call \`superdoc_get_content({action: "blocks", includeText: true})\`.
|
|
80921
|
+
- **From blocks data**: Each block has a \`ref\` (pass directly to superdoc_edit or superdoc_format), a \`nodeId\` (for building \`at\` positions with superdoc_create or \`where: {by: "block", ...}\` in superdoc_mutations), and optional full \`text\` when you call \`superdoc_get_content({action: "blocks", includeText: true})\`. Paragraph-class blocks have \`tabCount\` for the complete text; a compact \`textPreview\` can trim or truncate tabs. If \`tabCount > 0\`, read with \`includeText: true\` before editing.
|
|
80922
80922
|
- **From superdoc_search**: Returns \`handle.ref\` covering the matched text. Use search when you need to find text patterns, not when you already know which block to target.
|
|
80923
80923
|
- **From superdoc_create**: Returns \`nodeId\` and \`ref\`. The ref is valid for one immediate format call. For subsequent operations, re-fetch blocks to get fresh refs.
|
|
80924
80924
|
|
|
80925
80925
|
**Refs expire after any mutation** between separate tool calls. Within a superdoc_mutations batch, selectors resolve automatically — no manual re-searching between steps.
|
|
80926
80926
|
|
|
80927
|
-
**Critical targeting rule:** when rewriting an entire paragraph, clause, or other known block, first read \`superdoc_get_content({action: "blocks", includeText: true})\`, identify the block's \`nodeId\`, then use \`where: {by: "block", nodeType, nodeId}\` in \`superdoc_mutations\`. Do NOT use a shortened text selector to rewrite a whole clause.
|
|
80927
|
+
**Critical targeting rule:** when rewriting an entire paragraph, clause, or other known block, first read \`superdoc_get_content({action: "blocks", includeText: true})\`, identify the block's \`nodeId\`, then use \`where: {by: "block", nodeType, nodeId}\` in \`superdoc_mutations\`. Do NOT use a shortened text selector to rewrite a whole clause. Conversely, to change only a name or placeholder, select that exact text with \`superdoc_search\` and call \`superdoc_edit({action: "replace", ref: "<handle.ref>", text: "new name"})\`, or use a \`text.rewrite\` step with \`where: {by: "select", select: {type: "text", pattern: "old name"}, require: "exactlyOne"}\`. A whole-block plain-text rewrite that omits tabs deletes them; do not use it for a placeholder edit. Preserving tabs does not guarantee a visually aligned column if longer text crosses tab stops.
|
|
80928
80928
|
|
|
80929
80929
|
## Citation-grade output reads
|
|
80930
80930
|
|
|
@@ -81403,13 +81403,13 @@ One format.apply step per block. Combine \`inline\`, \`alignment\`, and \`scope:
|
|
|
81403
81403
|
|
|
81404
81404
|
Every editing tool needs a **target** telling the API *where* to apply the change. There are three ways to get one:
|
|
81405
81405
|
|
|
81406
|
-
- **From blocks data**: Each block has a \`ref\` (pass directly to superdoc_edit or superdoc_format), a \`nodeId\` (for building \`at\` positions with superdoc_create or \`where: {by: "block", ...}\` in superdoc_mutations), and optional full \`text\` when you call \`superdoc_get_content({action: "blocks", includeText: true})\`.
|
|
81406
|
+
- **From blocks data**: Each block has a \`ref\` (pass directly to superdoc_edit or superdoc_format), a \`nodeId\` (for building \`at\` positions with superdoc_create or \`where: {by: "block", ...}\` in superdoc_mutations), and optional full \`text\` when you call \`superdoc_get_content({action: "blocks", includeText: true})\`. Paragraph-class blocks have \`tabCount\` for the complete text; a compact \`textPreview\` can trim or truncate tabs. If \`tabCount > 0\`, read with \`includeText: true\` before editing.
|
|
81407
81407
|
- **From superdoc_search**: Returns \`handle.ref\` covering the matched text. Use search when you need to find text patterns, not when you already know which block to target.
|
|
81408
81408
|
- **From superdoc_create**: Returns \`nodeId\` and \`ref\`. The ref is valid for one immediate format call. For subsequent operations, re-fetch blocks to get fresh refs.
|
|
81409
81409
|
|
|
81410
81410
|
**Refs expire after any mutation** between separate tool calls. Within a superdoc_mutations batch, selectors resolve automatically — no manual re-searching between steps.
|
|
81411
81411
|
|
|
81412
|
-
**Critical targeting rule:** when rewriting an entire paragraph, clause, or other known block, first read \`superdoc_get_content({action: "blocks", includeText: true})\`, identify the block's \`nodeId\`, then use \`where: {by: "block", nodeType, nodeId}\` in \`superdoc_mutations\`. Do NOT use a shortened text selector to rewrite a whole clause.
|
|
81412
|
+
**Critical targeting rule:** when rewriting an entire paragraph, clause, or other known block, first read \`superdoc_get_content({action: "blocks", includeText: true})\`, identify the block's \`nodeId\`, then use \`where: {by: "block", nodeType, nodeId}\` in \`superdoc_mutations\`. Do NOT use a shortened text selector to rewrite a whole clause. Conversely, to change only a name or placeholder, select that exact text with \`superdoc_search\` and call \`superdoc_edit({action: "replace", ref: "<handle.ref>", text: "new name"})\`, or use a \`text.rewrite\` step with \`where: {by: "select", select: {type: "text", pattern: "old name"}, require: "exactlyOne"}\`. A whole-block plain-text rewrite that omits tabs deletes them; do not use it for a placeholder edit. Preserving tabs does not guarantee a visually aligned column if longer text crosses tab stops.
|
|
81413
81413
|
|
|
81414
81414
|
## Citation-grade output reads
|
|
81415
81415
|
|
|
@@ -82195,6 +82195,7 @@ function normalizeSnapshotBlock(value, fallbackOrdinal, blockTextLimit) {
|
|
|
82195
82195
|
nodeType: asString(rec.nodeType, "paragraph"),
|
|
82196
82196
|
text,
|
|
82197
82197
|
textPreview,
|
|
82198
|
+
...typeof rec.tabCount === "number" && Number.isInteger(rec.tabCount) && rec.tabCount >= 0 ? { tabCount: rec.tabCount } : {},
|
|
82198
82199
|
styleId: typeof rec.styleId === "string" ? rec.styleId : null,
|
|
82199
82200
|
headingLevel: typeof rec.headingLevel === "number" ? rec.headingLevel : undefined,
|
|
82200
82201
|
...asRecord(rec.numbering) ? {
|
|
@@ -92894,7 +92895,7 @@ var init_actions = __esm(() => {
|
|
|
92894
92895
|
operations: ["comments.create"]
|
|
92895
92896
|
},
|
|
92896
92897
|
rewrite_block: {
|
|
92897
|
-
hint: "selector, text, changeMode? — REPLACES the whole block text
|
|
92898
|
+
hint: "selector, text, changeMode? — REPLACES the whole block text. Omitted tab controls are deleted: for a tab-aligned paragraph, use replace_text with a minimal find span to change a name/placeholder instead. For appending a NEW paragraph/clause use insert_paragraphs",
|
|
92898
92899
|
group: "Text/structure actions",
|
|
92899
92900
|
groupOrder: 7,
|
|
92900
92901
|
args: ["text", "selector", "changeMode", "evidence"],
|
|
@@ -96324,7 +96325,7 @@ var init_operation_definitions = __esm(() => {
|
|
|
96324
96325
|
},
|
|
96325
96326
|
get_content: {
|
|
96326
96327
|
toolName: "superdoc_get_content",
|
|
96327
|
-
description: "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. " + 'Action "blocks" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. ' + 'When you need to evaluate or rewrite existing paragraphs or clauses, prefer action "blocks" with includeText:true so you can identify the correct block and then target it by nodeId. ' + 'Actions "text", "markdown", and "html" return compact strings. Actions "markdown_projection" and "html_projection" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. ' + "Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. " + 'Action "info" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. ' + 'The "blocks" action supports pagination via "offset" and "limit", filtering via "nodeTypes", and numbering projection via "reviewMode". Other actions ignore pagination and filtering parameters. ' + "This tool never modifies the document. " + "Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.",
|
|
96328
|
+
description: "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. " + 'Action "blocks" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. ' + 'When you need to evaluate or rewrite existing paragraphs or clauses, prefer action "blocks" with includeText:true so you can identify the correct block and then target it by nodeId. ' + 'Actions "text", "markdown", and "html" return compact strings. Actions "markdown_projection" and "html_projection" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. ' + "Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. " + 'Action "info" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. ' + 'The "blocks" action supports pagination via "offset" and "limit", filtering via "nodeTypes", and numbering projection via "reviewMode". Other actions ignore pagination and filtering parameters. ' + "This tool never modifies the document. " + "Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.",
|
|
96328
96329
|
inputExamples: [
|
|
96329
96330
|
{ action: "blocks" },
|
|
96330
96331
|
{ action: "blocks", includeText: true, offset: 0, limit: 20, reviewMode: "final" },
|
|
@@ -96616,7 +96617,7 @@ Complete new body.`,
|
|
|
96616
96617
|
section: { toolName: "superdoc_section", description: "Page layout, margins, columns" },
|
|
96617
96618
|
mutations: {
|
|
96618
96619
|
toolName: "superdoc_mutations",
|
|
96619
|
-
description: "All steps succeed or all fail; no partial application. " + "Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. " + "Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. " + 'Each step has an id, an op, a "where" clause for targeting ({by:"select", select:{...}, require:"first"|"exactlyOne"|"all"} or {by:"ref", ref:"..."} or {by:"block", nodeType:"paragraph", nodeId:"..."}), and "args" with operation-specific parameters. ' + 'Use {by:"block", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action "blocks" without relying on text matching. ' + 'For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:"blocks" and includeText:true, then rewrite the matching block by nodeId. ' + 'Use {by:"select"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. ' + 'For create steps, "where" targets an existing anchor block and args.position ("before" or "after") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. ' + 'For format.apply with require "all", use a node selector to format every heading or paragraph at once: {by:"select", select:{type:"node", nodeType:"heading"}, require:"all"}. ' + "Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. " + 'Action "preview" dry-runs the plan. Action "apply" executes it. ' + "If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. " + "Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.",
|
|
96620
|
+
description: "All steps succeed or all fail; no partial application. " + "Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. " + "Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. " + 'Each step has an id, an op, a "where" clause for targeting ({by:"select", select:{...}, require:"first"|"exactlyOne"|"all"} or {by:"ref", ref:"..."} or {by:"block", nodeType:"paragraph", nodeId:"..."}), and "args" with operation-specific parameters. ' + 'Use {by:"block", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action "blocks" without relying on text matching. ' + 'For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:"blocks" and includeText:true, then rewrite the matching block by nodeId. ' + 'For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:"select" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. ' + 'Use {by:"select"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. ' + 'For create steps, "where" targets an existing anchor block and args.position ("before" or "after") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. ' + 'For format.apply with require "all", use a node selector to format every heading or paragraph at once: {by:"select", select:{type:"node", nodeType:"heading"}, require:"all"}. ' + "Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. " + 'Action "preview" dry-runs the plan. Action "apply" executes it. ' + "If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. " + "Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.",
|
|
96620
96621
|
inputExamples: [
|
|
96621
96622
|
{
|
|
96622
96623
|
action: "apply",
|
|
@@ -109129,6 +109130,11 @@ var init_schemas4 = __esm(() => {
|
|
|
109129
109130
|
oneOf: [{ type: "string" }, { type: "null" }],
|
|
109130
109131
|
description: "Full flattened block text when requested with includeText."
|
|
109131
109132
|
},
|
|
109133
|
+
tabCount: {
|
|
109134
|
+
type: "integer",
|
|
109135
|
+
minimum: 0,
|
|
109136
|
+
description: "Tabs in complete paragraph text, even beyond the preview."
|
|
109137
|
+
},
|
|
109132
109138
|
isEmpty: { type: "boolean" },
|
|
109133
109139
|
styleId: { oneOf: [{ type: "string" }, { type: "null" }], description: "Named paragraph style." },
|
|
109134
109140
|
fontFamily: { type: "string", description: "Font family from first text run." },
|
|
@@ -124582,6 +124588,13 @@ function parseItem(source, item, ctx) {
|
|
|
124582
124588
|
return [];
|
|
124583
124589
|
case "r":
|
|
124584
124590
|
return parseRun(source, item, ctx);
|
|
124591
|
+
case "br":
|
|
124592
|
+
if (!isWordprocessingElement(item, ctx.namespaceBindings)) {
|
|
124593
|
+
return [buildDescendingContainer(source, item, ctx, "unknown", "fail-closed")];
|
|
124594
|
+
}
|
|
124595
|
+
return [makeContainerPiece(item, ctx, "unknown", "fail-closed", [
|
|
124596
|
+
buildControlPiece(item, ctx, null, item.byteStart, item.byteEnd, item.charStart, item.charEnd, "", "")
|
|
124597
|
+
])];
|
|
124585
124598
|
case "ins":
|
|
124586
124599
|
case "del":
|
|
124587
124600
|
case "moveFrom":
|
|
@@ -125588,6 +125601,9 @@ function projectElement(xml, elementStart, element, deleted, instruction, namesp
|
|
|
125588
125601
|
if (element.selfClosing) {
|
|
125589
125602
|
if (localName === "r")
|
|
125590
125603
|
projectRun2(xml, elementStart, element, deleted, instruction, namespaceScopes, collector);
|
|
125604
|
+
if (localName === "br" && isWordprocessingElement2(xml, elementStart, element, namespaceScopes, collector.inferredWordPrefix))
|
|
125605
|
+
appendControl(collector, `
|
|
125606
|
+
`, deleted);
|
|
125591
125607
|
return;
|
|
125592
125608
|
}
|
|
125593
125609
|
switch (localName) {
|
|
@@ -125599,6 +125615,16 @@ function projectElement(xml, elementStart, element, deleted, instruction, namesp
|
|
|
125599
125615
|
case "r":
|
|
125600
125616
|
projectRun2(xml, elementStart, element, deleted, instruction, namespaceScopes, collector);
|
|
125601
125617
|
return;
|
|
125618
|
+
case "br":
|
|
125619
|
+
if (isWordprocessingElement2(xml, elementStart, element, namespaceScopes, collector.inferredWordPrefix)) {
|
|
125620
|
+
appendControl(collector, `
|
|
125621
|
+
`, deleted);
|
|
125622
|
+
return;
|
|
125623
|
+
}
|
|
125624
|
+
withNamespaceScope(namespaceScopes, elementStart, element.openEnd, () => {
|
|
125625
|
+
projectChildSequence(xml, element.openEnd, element.closeStart, deleted, instruction, namespaceScopes, collector);
|
|
125626
|
+
});
|
|
125627
|
+
return;
|
|
125602
125628
|
case "del":
|
|
125603
125629
|
case "moveFrom":
|
|
125604
125630
|
withNamespaceScope(namespaceScopes, elementStart, element.openEnd, () => {
|
|
@@ -133951,6 +133977,50 @@ var init_note_xml_validation = __esm(() => {
|
|
|
133951
133977
|
});
|
|
133952
133978
|
|
|
133953
133979
|
// ../../../v2/document-compare/src/replayability.ts
|
|
133980
|
+
function preservedBookmarkRunTokens(xml) {
|
|
133981
|
+
const markerTags = [...xml.matchAll(/<([\w.-]+:)?bookmark(Start|End)\b[^<>]*?\/>/g)];
|
|
133982
|
+
const markerOpenings = [...xml.matchAll(/<(?:[\w.-]+:)?bookmark(?:Start|End)\b/g)];
|
|
133983
|
+
if (markerTags.length !== 2 || markerOpenings.length !== 2 || markerTags[0][2] !== "Start" || markerTags[1][2] !== "End")
|
|
133984
|
+
return null;
|
|
133985
|
+
let valid = true;
|
|
133986
|
+
let depth = 0;
|
|
133987
|
+
const markers = [];
|
|
133988
|
+
const parser = new import_saxes3.SaxesParser({
|
|
133989
|
+
xmlns: true,
|
|
133990
|
+
additionalNamespaces: replayAdditionalNamespaces(xml)
|
|
133991
|
+
});
|
|
133992
|
+
parser.on("error", () => {
|
|
133993
|
+
valid = false;
|
|
133994
|
+
});
|
|
133995
|
+
parser.on("opentag", (tag) => {
|
|
133996
|
+
depth += 1;
|
|
133997
|
+
if (tag.local !== "bookmarkStart" && tag.local !== "bookmarkEnd")
|
|
133998
|
+
return;
|
|
133999
|
+
const attributes = Object.values(tag.attributes);
|
|
134000
|
+
const id = attributes.find((attribute) => attribute.uri === W_NS && attribute.local === "id")?.value;
|
|
134001
|
+
const name = attributes.find((attribute) => attribute.uri === W_NS && attribute.local === "name")?.value ?? null;
|
|
134002
|
+
if (tag.uri !== W_NS || !tag.isSelfClosing || depth !== 2 || !id || !/^\d+$/.test(id) || tag.local === "bookmarkStart" && !name || tag.local === "bookmarkEnd" && name !== null)
|
|
134003
|
+
valid = false;
|
|
134004
|
+
markers.push({ kind: tag.local, id: id ?? "", name });
|
|
134005
|
+
});
|
|
134006
|
+
parser.on("closetag", () => {
|
|
134007
|
+
depth -= 1;
|
|
134008
|
+
});
|
|
134009
|
+
try {
|
|
134010
|
+
parser.write(`<replay>${xml}</replay>`).close();
|
|
134011
|
+
} catch {
|
|
134012
|
+
valid = false;
|
|
134013
|
+
}
|
|
134014
|
+
if (!valid || depth !== 0 || markers.length !== 2 || markers[0].kind !== "bookmarkStart" || markers[1].kind !== "bookmarkEnd" || markers[0].id !== markers[1].id)
|
|
134015
|
+
return null;
|
|
134016
|
+
return {
|
|
134017
|
+
startXml: markerTags[0][0],
|
|
134018
|
+
endXml: markerTags[1][0],
|
|
134019
|
+
leadingXml: xml.slice(0, markerTags[0].index),
|
|
134020
|
+
trailingXml: xml.slice(markerTags[1].index + markerTags[1][0].length),
|
|
134021
|
+
strippedXml: xml.slice(0, markerTags[0].index) + xml.slice(markerTags[0].index + markerTags[0][0].length, markerTags[1].index) + xml.slice(markerTags[1].index + markerTags[1][0].length)
|
|
134022
|
+
};
|
|
134023
|
+
}
|
|
133954
134024
|
function replayAdditionalNamespaces(xml) {
|
|
133955
134025
|
const implicitNamespaces = { w: W_NS };
|
|
133956
134026
|
const firstElement = /<([A-Za-z_][\w.-]*)(?::[A-Za-z_][\w.-]*)?(?=[\s/>])/.exec(xml);
|
|
@@ -134078,6 +134148,13 @@ function parseDirectRunSequence(xml, allowRevisions) {
|
|
|
134078
134148
|
originalText += value;
|
|
134079
134149
|
}
|
|
134080
134150
|
};
|
|
134151
|
+
const isProofingBoundary = (tag) => {
|
|
134152
|
+
if (tag.uri !== W_NS || tag.local !== "proofErr" || !tag.isSelfClosing)
|
|
134153
|
+
return false;
|
|
134154
|
+
const attributes = Object.values(tag.attributes);
|
|
134155
|
+
const typeAttributes = attributes.filter((attribute) => typeof attribute !== "string" && attribute.uri === W_NS && attribute.local === "type");
|
|
134156
|
+
return typeAttributes.length === 1 && typeof typeAttributes[0] !== "string" && PROOFING_BOUNDARY_TYPES.has(typeAttributes[0].value) && attributes.every((attribute) => typeof attribute !== "string" && (attribute === typeAttributes[0] || attribute.uri === "http://www.w3.org/2000/xmlns/" && (attribute.local === tag.prefix || attribute.local === "w" || tag.prefix === "" && attribute.local === "xmlns") && attribute.value === W_NS));
|
|
134157
|
+
};
|
|
134081
134158
|
const parser = new import_saxes3.SaxesParser({
|
|
134082
134159
|
xmlns: true,
|
|
134083
134160
|
additionalNamespaces: replayAdditionalNamespaces(xml)
|
|
@@ -134094,6 +134171,10 @@ function parseDirectRunSequence(xml, allowRevisions) {
|
|
|
134094
134171
|
return;
|
|
134095
134172
|
}
|
|
134096
134173
|
if (parent === "wrapper") {
|
|
134174
|
+
if (isProofingBoundary(tag)) {
|
|
134175
|
+
stack.push("control");
|
|
134176
|
+
return;
|
|
134177
|
+
}
|
|
134097
134178
|
rootCount += 1;
|
|
134098
134179
|
if (tag.uri === W_NS && tag.local === "r") {
|
|
134099
134180
|
stack.push("run");
|
|
@@ -134124,6 +134205,10 @@ function parseDirectRunSequence(xml, allowRevisions) {
|
|
|
134124
134205
|
return;
|
|
134125
134206
|
}
|
|
134126
134207
|
if (parent === "revision") {
|
|
134208
|
+
if (isProofingBoundary(tag)) {
|
|
134209
|
+
stack.push("control");
|
|
134210
|
+
return;
|
|
134211
|
+
}
|
|
134127
134212
|
if (tag.uri !== W_NS || tag.local !== "r")
|
|
134128
134213
|
valid = false;
|
|
134129
134214
|
activeRevisionRunCount += 1;
|
|
@@ -134550,13 +134635,14 @@ function validateRunContents(xml, options) {
|
|
|
134550
134635
|
if (xml === "")
|
|
134551
134636
|
return { ok: true };
|
|
134552
134637
|
const replayXml = stripAllowedNoteReferences(xml, options);
|
|
134553
|
-
|
|
134638
|
+
const withoutBookmarks = replayXml !== null && /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(replayXml) ? preservedBookmarkRunTokens(replayXml)?.strippedXml ?? null : replayXml;
|
|
134639
|
+
if (withoutBookmarks === null || UNSUPPORTED_XML.test(withoutBookmarks) || RELATIONSHIP_REFERENCE.test(withoutBookmarks)) {
|
|
134554
134640
|
return { ok: false, reason: "target runs require unsupported structural or relationship replay" };
|
|
134555
134641
|
}
|
|
134556
|
-
const namespaceResult = validateReplayNamespaces(
|
|
134642
|
+
const namespaceResult = validateReplayNamespaces(withoutBookmarks.replace(PROOFING_BOUNDARY_TAG_RE, ""), "target runs use namespace prefixes that cannot be replayed safely");
|
|
134557
134643
|
if (!namespaceResult.ok)
|
|
134558
134644
|
return namespaceResult;
|
|
134559
|
-
if (!parseDirectRunSequence(
|
|
134645
|
+
if (!parseDirectRunSequence(withoutBookmarks, false)) {
|
|
134560
134646
|
return { ok: false, reason: "target runs contain unsupported inline markup" };
|
|
134561
134647
|
}
|
|
134562
134648
|
return { ok: true };
|
|
@@ -134580,7 +134666,7 @@ function validateCompareReplayPayload(payload, options = {}) {
|
|
|
134580
134666
|
if (payload.targetRevisionReplay.policy !== "preserve-target-revision-set" || payload.targetRunXml === undefined) {
|
|
134581
134667
|
return { ok: false, reason: "target revision replay policy is incomplete" };
|
|
134582
134668
|
}
|
|
134583
|
-
const namespaceResult = validateReplayNamespaces(payload.targetRunXml, "target revision runs use namespace prefixes that cannot be replayed safely");
|
|
134669
|
+
const namespaceResult = validateReplayNamespaces(payload.targetRunXml.replace(PROOFING_BOUNDARY_TAG_RE, ""), "target revision runs use namespace prefixes that cannot be replayed safely");
|
|
134584
134670
|
if (!namespaceResult.ok)
|
|
134585
134671
|
return namespaceResult;
|
|
134586
134672
|
const inspected = inspectDirectParagraphRevisionRuns(payload.targetRunXml);
|
|
@@ -134600,12 +134686,14 @@ function validateCompareReplayPayload(payload, options = {}) {
|
|
|
134600
134686
|
}
|
|
134601
134687
|
return { ok: true };
|
|
134602
134688
|
}
|
|
134603
|
-
var import_saxes3, UNSUPPORTED_XML, RELATIONSHIP_REFERENCE, W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", DIRECT_RUN_PROPERTY_ELEMENTS;
|
|
134689
|
+
var import_saxes3, UNSUPPORTED_XML, RELATIONSHIP_REFERENCE, W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", PROOFING_BOUNDARY_TYPES, PROOFING_BOUNDARY_TAG_RE, DIRECT_RUN_PROPERTY_ELEMENTS;
|
|
134604
134690
|
var init_replayability = __esm(() => {
|
|
134605
134691
|
init_note_xml_validation();
|
|
134606
134692
|
import_saxes3 = __toESM(require_saxes(), 1);
|
|
134607
|
-
UNSUPPORTED_XML = /<(?:[\w.-]+:)?(?:hyperlink|drawing|pict|object|fldSimple|fldChar|instrText|commentReference|commentRangeStart|commentRangeEnd|
|
|
134693
|
+
UNSUPPORTED_XML = /<(?:[\w.-]+:)?(?:hyperlink|drawing|pict|object|fldSimple|fldChar|instrText|commentReference|commentRangeStart|commentRangeEnd|permStart|permEnd|sdt|customXml|oMath|oMathPara|footnoteReference|endnoteReference|ins|del|moveFrom|moveTo|pPrChange|rPrChange|sectPr)\b/i;
|
|
134608
134694
|
RELATIONSHIP_REFERENCE = /\s(?:r:id|r:embed|r:link)\s*=/i;
|
|
134695
|
+
PROOFING_BOUNDARY_TYPES = new Set(["spellStart", "spellEnd", "gramStart", "gramEnd"]);
|
|
134696
|
+
PROOFING_BOUNDARY_TAG_RE = /<(?:[A-Za-z_][\w.-]*:)?proofErr\b(?:[^>"']|"[^"]*"|'[^']*')*\/>/g;
|
|
134609
134697
|
DIRECT_RUN_PROPERTY_ELEMENTS = new Set([
|
|
134610
134698
|
"rStyle",
|
|
134611
134699
|
"rFonts",
|
|
@@ -134745,7 +134833,10 @@ function canonicalName(namespace, localName2) {
|
|
|
134745
134833
|
}
|
|
134746
134834
|
function computeRunSignature(runXml) {
|
|
134747
134835
|
const canonicalXml = canonicalizeXmlForSignature(runXml);
|
|
134748
|
-
const normalized = normalizeRunXmlForSignature(canonicalXml.replace(REVISION_ATTR_RE,
|
|
134836
|
+
const normalized = normalizeRunXmlForSignature(canonicalXml.replace(REVISION_ATTR_RE, (attribute, offset, xml) => {
|
|
134837
|
+
const precedingTag = xml.slice(xml.lastIndexOf("<", offset), offset);
|
|
134838
|
+
return /^<w:proofErr(?:\s|$)/.test(precedingTag) ? attribute : "";
|
|
134839
|
+
}).replace(REVISION_ELEMENT_RE, (markup) => markup.replace(REVISION_ID_ATTR_RE, "")).replace(COMMENT_MARKUP_RE, (markup, name, attributes) => isWordprocessingElement3(name, attributes, canonicalXml) ? "" : markup).replace(NOTE_REFERENCE_MARKUP_RE, (markup, runName, runAttributes, _rPrName, nestedName, nestedAttributes, standaloneName, standaloneAttributes) => {
|
|
134749
134840
|
const name = nestedName ?? standaloneName;
|
|
134750
134841
|
const attributes = nestedAttributes ?? standaloneAttributes;
|
|
134751
134842
|
if (!isWordprocessingElement3(name, attributes, canonicalXml))
|
|
@@ -134772,7 +134863,7 @@ function normalizeRunXmlForSignature(runXml) {
|
|
|
134772
134863
|
continue;
|
|
134773
134864
|
const index = match.index ?? 0;
|
|
134774
134865
|
if (index > lastIndex) {
|
|
134775
|
-
const interstitial = runXml.slice(lastIndex, index);
|
|
134866
|
+
const interstitial = stripProofingBoundaries(runXml.slice(lastIndex, index));
|
|
134776
134867
|
if (interstitial.trim().length > 0) {
|
|
134777
134868
|
pieces.push(interstitial);
|
|
134778
134869
|
activeTextProperties = "";
|
|
@@ -134801,12 +134892,15 @@ function normalizeRunXmlForSignature(runXml) {
|
|
|
134801
134892
|
if (!sawRun)
|
|
134802
134893
|
return runXml;
|
|
134803
134894
|
if (lastIndex < runXml.length) {
|
|
134804
|
-
const trailing = runXml.slice(lastIndex);
|
|
134895
|
+
const trailing = stripProofingBoundaries(runXml.slice(lastIndex));
|
|
134805
134896
|
if (trailing.trim().length > 0)
|
|
134806
134897
|
pieces.push(trailing);
|
|
134807
134898
|
}
|
|
134808
134899
|
return pieces.join("");
|
|
134809
134900
|
}
|
|
134901
|
+
function stripProofingBoundaries(xml) {
|
|
134902
|
+
return xml.replace(PROOFING_BOUNDARY_MARKUP_RE, "");
|
|
134903
|
+
}
|
|
134810
134904
|
function normalizeRunControls(content, namespaceContext) {
|
|
134811
134905
|
return [...content.matchAll(RUN_CONTROL_RE)].filter((match) => isWordprocessingElement3(match[1], match[3], namespaceContext)).map((match) => {
|
|
134812
134906
|
const attributes = [...match[3].matchAll(ATTRIBUTE_RE)].filter((attribute) => attribute[1] !== "xmlns" && !attribute[1].startsWith("xmlns:")).map((attribute) => {
|
|
@@ -134839,10 +134933,13 @@ function isWordprocessingElement3(name, attributes, namespaceContext) {
|
|
|
134839
134933
|
return true;
|
|
134840
134934
|
return (declaration[2] ?? declaration[3] ?? "") === WORDPROCESSINGML_NAMESPACE2;
|
|
134841
134935
|
}
|
|
134842
|
-
var REVISION_ATTR_RE, COMMENT_MARKUP_RE, NOTE_REFERENCE_MARKUP_RE, RUN_RE, RUN_PROPERTIES_RE, EMPTY_RUN_PROPERTIES_RE, TEXTISH_RE, RUN_CONTROL_RE, ATTRIBUTE_RE, WORDPROCESSINGML_NAMESPACE2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORDPROCESSINGML_2010_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml", MARKUP_COMPATIBILITY_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006", XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace", XML_TAG_RE;
|
|
134936
|
+
var REVISION_ATTR_RE, REVISION_ELEMENT_RE, REVISION_ID_ATTR_RE, COMMENT_MARKUP_RE, PROOFING_BOUNDARY_MARKUP_RE, NOTE_REFERENCE_MARKUP_RE, RUN_RE, RUN_PROPERTIES_RE, EMPTY_RUN_PROPERTIES_RE, TEXTISH_RE, RUN_CONTROL_RE, ATTRIBUTE_RE, WORDPROCESSINGML_NAMESPACE2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORDPROCESSINGML_2010_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml", MARKUP_COMPATIBILITY_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006", XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace", XML_TAG_RE;
|
|
134843
134937
|
var init_run_signature = __esm(() => {
|
|
134844
|
-
REVISION_ATTR_RE = /\s+(?:w:rsid\w*|w14:paraId|w14:textId
|
|
134938
|
+
REVISION_ATTR_RE = /\s+(?:w:rsid\w*|w14:paraId|w14:textId)="[^"]*"/g;
|
|
134939
|
+
REVISION_ELEMENT_RE = /<w:(?:ins|del|moveFrom|moveTo)\b[^>]*>/g;
|
|
134940
|
+
REVISION_ID_ATTR_RE = /\s+w:id="[^"]*"/g;
|
|
134845
134941
|
COMMENT_MARKUP_RE = /<((?:[\w.-]+:)?(?:commentRangeStart|commentRangeEnd|commentReference))\b([^>]*)\/>/g;
|
|
134942
|
+
PROOFING_BOUNDARY_MARKUP_RE = /<w:proofErr w:type="(?:spellStart|spellEnd|gramStart|gramEnd)"\/>/g;
|
|
134846
134943
|
NOTE_REFERENCE_MARKUP_RE = /<((?:[\w.-]+:)?r)\b([^>]*)>(?:<((?:[\w.-]+:)?rPr)\b[^>]*(?:\/>|>[\s\S]*?<\/\3>))?<((?:[\w.-]+:)?(?:footnoteReference|endnoteReference))\b([^>]*)\/><\/\1>|<((?:[\w.-]+:)?(?:footnoteReference|endnoteReference))\b([^>]*)\/>/g;
|
|
134847
134944
|
RUN_RE = /<((?:[\w.-]+:)?r)\b([^>]*)>([\s\S]*?)<\/\1>/g;
|
|
134848
134945
|
RUN_PROPERTIES_RE = /<((?:[\w.-]+:)?rPr)\b([^>]*)(?:\/>|>[\s\S]*?<\/\1>)/g;
|
|
@@ -141958,7 +142055,7 @@ var init_story_slice = __esm(() => {
|
|
|
141958
142055
|
init_source_coverage_chunks();
|
|
141959
142056
|
DEFAULT_MAX_XML_BYTES = 64 * 1024;
|
|
141960
142057
|
TEXT_DECODER = new TextDecoder("utf-8", { fatal: false });
|
|
141961
|
-
NODE_BUFFER = typeof globalThis !== "undefined" && typeof globalThis.Buffer?.byteLength === "function" ? globalThis.Buffer : null;
|
|
142058
|
+
NODE_BUFFER = typeof globalThis !== "undefined" && typeof globalThis.process?.versions?.node === "string" && typeof globalThis.Buffer?.byteLength === "function" ? globalThis.Buffer : null;
|
|
141962
142059
|
CHUNK_SPAN_CACHE = new WeakMap;
|
|
141963
142060
|
});
|
|
141964
142061
|
|
|
@@ -178481,6 +178578,37 @@ function canonicalizeDependencyValue(value) {
|
|
|
178481
178578
|
}
|
|
178482
178579
|
return value;
|
|
178483
178580
|
}
|
|
178581
|
+
function locateSingleResidentBodyChild(state, storyId, partUri, chunk, paragraphByteStart, paragraphByteEnd, containingBodyChildOrdinal) {
|
|
178582
|
+
const story = state.stories.get(storyId)?.descriptor;
|
|
178583
|
+
const part = state.parts.get(partUri)?.descriptor;
|
|
178584
|
+
if (storyId !== state.mainStoryId || story?.storyId !== storyId || story.storyKind !== "main" || story.ownerPartId !== partUri || story.ownerPartUri !== partUri || part?.partId !== partUri || part.partUri !== partUri || chunk.storyId !== storyId || chunk.partUri !== partUri || chunk.storyRevision !== story.revision || !state.packageBytes.has(partUri))
|
|
178585
|
+
return null;
|
|
178586
|
+
const residentByteLength = state.packageBytes.byteLength(partUri);
|
|
178587
|
+
const { byteStart, byteEnd, bodyChildStartOrdinal, bodyChildEndOrdinal, contentBlockStartOrdinal, contentBlockEndOrdinal, firstChildKind, lastChildKind, bodyChildCount, contentBlockCount, markerChildCount, opaqueAnchorCount, containsTrivia, triviaByteSpans } = chunk;
|
|
178588
|
+
if (residentByteLength == null || !Number.isSafeInteger(residentByteLength) || !Number.isSafeInteger(byteStart) || !Number.isSafeInteger(byteEnd) || byteStart < 0 || byteEnd <= byteStart || byteEnd > residentByteLength || !Number.isSafeInteger(paragraphByteStart) || !Number.isSafeInteger(paragraphByteEnd) || paragraphByteStart < byteStart || paragraphByteEnd <= paragraphByteStart || paragraphByteEnd > byteEnd || !Number.isSafeInteger(containingBodyChildOrdinal) || containingBodyChildOrdinal < 0 || bodyChildCount !== 1 || bodyChildStartOrdinal !== containingBodyChildOrdinal || bodyChildEndOrdinal !== containingBodyChildOrdinal || contentBlockCount !== 1 || contentBlockStartOrdinal == null || !Number.isSafeInteger(contentBlockStartOrdinal) || contentBlockStartOrdinal < 0 || contentBlockEndOrdinal !== contentBlockStartOrdinal || markerChildCount !== 0 || opaqueAnchorCount !== 0 || firstChildKind !== lastChildKind || firstChildKind !== "p" && firstChildKind !== "tbl" && firstChildKind !== "sdt")
|
|
178589
|
+
return null;
|
|
178590
|
+
let ownerByteStart = byteStart;
|
|
178591
|
+
if (triviaByteSpans.length === 0) {
|
|
178592
|
+
if (containsTrivia)
|
|
178593
|
+
return null;
|
|
178594
|
+
} else {
|
|
178595
|
+
if (!containsTrivia || triviaByteSpans.length !== 1)
|
|
178596
|
+
return null;
|
|
178597
|
+
const [triviaStart, triviaEnd] = triviaByteSpans[0];
|
|
178598
|
+
if (triviaStart !== byteStart || !Number.isSafeInteger(triviaEnd) || triviaEnd <= triviaStart || triviaEnd >= byteEnd)
|
|
178599
|
+
return null;
|
|
178600
|
+
ownerByteStart = triviaEnd;
|
|
178601
|
+
}
|
|
178602
|
+
if (paragraphByteStart < ownerByteStart)
|
|
178603
|
+
return null;
|
|
178604
|
+
return {
|
|
178605
|
+
status: "ok",
|
|
178606
|
+
bodyChildOrdinal: bodyChildStartOrdinal,
|
|
178607
|
+
localName: firstChildKind,
|
|
178608
|
+
byteStart: ownerByteStart,
|
|
178609
|
+
byteEnd
|
|
178610
|
+
};
|
|
178611
|
+
}
|
|
178484
178612
|
function locateExactResidentBodyChild(state, storyId, partUri, byteStart, byteEnd, cache) {
|
|
178485
178613
|
const chunks = findChunksContainingRange(state.sourceCoverage.get(storyId)?.chunks ?? [], partUri, byteStart, byteEnd);
|
|
178486
178614
|
if (chunks.length === 0)
|
|
@@ -178539,14 +178667,20 @@ function locateContainingResidentBodyChild(state, storyId, partUri, paragraphByt
|
|
|
178539
178667
|
const chunks = findChunksContainingRange(state.sourceCoverage.get(storyId)?.chunks ?? [], partUri, paragraphByteStart, paragraphByteEnd);
|
|
178540
178668
|
if (chunks.length === 0)
|
|
178541
178669
|
return { status: "failed", reason: "body-child-not-found" };
|
|
178542
|
-
|
|
178543
|
-
if (!bytes)
|
|
178544
|
-
return { status: "failed", reason: "body-child-not-found" };
|
|
178670
|
+
let bytes;
|
|
178545
178671
|
const matches = [];
|
|
178546
178672
|
for (const chunk of chunks) {
|
|
178547
178673
|
const relativeOrdinal = containingBodyChildOrdinal - chunk.bodyChildStartOrdinal;
|
|
178548
178674
|
if (relativeOrdinal < 0 || containingBodyChildOrdinal > chunk.bodyChildEndOrdinal)
|
|
178549
178675
|
continue;
|
|
178676
|
+
const singleChild = locateSingleResidentBodyChild(state, storyId, partUri, chunk, paragraphByteStart, paragraphByteEnd, containingBodyChildOrdinal);
|
|
178677
|
+
if (singleChild) {
|
|
178678
|
+
matches.push(singleChild);
|
|
178679
|
+
continue;
|
|
178680
|
+
}
|
|
178681
|
+
bytes ?? (bytes = state.packageBytes.get(partUri));
|
|
178682
|
+
if (!bytes)
|
|
178683
|
+
return { status: "failed", reason: "body-child-not-found" };
|
|
178550
178684
|
const chunkXml = TD24.decode(bytes.subarray(chunk.byteStart, chunk.byteEnd));
|
|
178551
178685
|
const spans = listTopLevelElementSpans2(chunkXml);
|
|
178552
178686
|
const span = spans[relativeOrdinal];
|
|
@@ -212431,10 +212565,16 @@ function prepareParagraphDelete(state, op) {
|
|
|
212431
212565
|
return { ok: true, noOp: true, target, bytes, xml, paraXml, successor };
|
|
212432
212566
|
}
|
|
212433
212567
|
const structural = classifyParagraphStructural(paraXml, {
|
|
212434
|
-
allowRelationshipBearing: true
|
|
212568
|
+
allowRelationshipBearing: true,
|
|
212569
|
+
allowInlineSdtDeletion: changeMode === "direct"
|
|
212435
212570
|
});
|
|
212436
212571
|
if (!structural.ok)
|
|
212437
212572
|
return { ok: false, reason: structural.reason };
|
|
212573
|
+
if (changeMode === "direct") {
|
|
212574
|
+
const sdtFailure = validateDirectParagraphInlineSdtDeletion(bytes, target.entry.byteStart, paraXml);
|
|
212575
|
+
if (sdtFailure)
|
|
212576
|
+
return { ok: false, reason: sdtFailure };
|
|
212577
|
+
}
|
|
212438
212578
|
const namespaces = /(?:drawing|pict)/.test(paraXml) ? namespaceBindingsAtPosition(bytes, target.entry.byteStart, matchParagraphOpenTag(paraXml) ?? "") : undefined;
|
|
212439
212579
|
const hasDrawing = namespaces && collectXmlElementRanges(paraXml, {
|
|
212440
212580
|
fragment: true,
|
|
@@ -214170,6 +214310,30 @@ function tableOrdinalAtOrBeforeByte(catalog, byteOffset) {
|
|
|
214170
214310
|
}
|
|
214171
214311
|
return low - 1;
|
|
214172
214312
|
}
|
|
214313
|
+
function validateDirectParagraphInlineSdtDeletion(bytes, paragraphStartByte, paraXml) {
|
|
214314
|
+
const sdtTags = paraXml.match(/<\s*(?:[\w.-]+:)?sdt\b/g);
|
|
214315
|
+
if (!sdtTags)
|
|
214316
|
+
return null;
|
|
214317
|
+
const namespaces = namespaceBindingsAtPosition(bytes, paragraphStartByte, matchParagraphOpenTag(paraXml) ?? "");
|
|
214318
|
+
const pieces = parseParagraphInlineMap(paraXml, namespaces).pieces;
|
|
214319
|
+
let sdtCount = 0;
|
|
214320
|
+
for (const piece of pieces) {
|
|
214321
|
+
if (piece.kind !== "container" || piece.containerKind !== "sdt")
|
|
214322
|
+
continue;
|
|
214323
|
+
sdtCount += 1;
|
|
214324
|
+
const policy = classifySdtMutationPolicy(piece);
|
|
214325
|
+
if (!policy.ok)
|
|
214326
|
+
return policy.reason;
|
|
214327
|
+
if (!policy.wrapperDeletable)
|
|
214328
|
+
return "text-range-in-sdt";
|
|
214329
|
+
const blocked = findBlockingSdtChild(piece.children);
|
|
214330
|
+
if (blocked)
|
|
214331
|
+
return blocked;
|
|
214332
|
+
}
|
|
214333
|
+
if (sdtCount !== sdtTags.length)
|
|
214334
|
+
return "text-range-in-sdt";
|
|
214335
|
+
return null;
|
|
214336
|
+
}
|
|
214173
214337
|
function classifyParagraphStructural(paraXml, options = {}) {
|
|
214174
214338
|
if (/<[\w.-]+:moveFrom\b/.test(paraXml) || /<[\w.-]+:moveTo\b/.test(paraXml)) {
|
|
214175
214339
|
return { ok: false, reason: "paragraph-tracked-wrapper-unsupported" };
|
|
@@ -214177,7 +214341,7 @@ function classifyParagraphStructural(paraXml, options = {}) {
|
|
|
214177
214341
|
if (!options.fieldsVerified && (/<[\w.-]+:fldChar\b/.test(paraXml) || /<[\w.-]+:instrText\b/.test(paraXml) || /<[\w.-]+:fldSimple\b/.test(paraXml))) {
|
|
214178
214342
|
return { ok: false, reason: "paragraph-tracked-wrapper-unsupported" };
|
|
214179
214343
|
}
|
|
214180
|
-
if (/<[\w.-]+:sdt\b/.test(paraXml)) {
|
|
214344
|
+
if (!options.allowInlineSdtDeletion && /<[\w.-]+:sdt\b/.test(paraXml)) {
|
|
214181
214345
|
return { ok: false, reason: "paragraph-tracked-wrapper-unsupported" };
|
|
214182
214346
|
}
|
|
214183
214347
|
let relationshipBearing = false;
|
|
@@ -214964,6 +215128,7 @@ var init_compile_paragraph_ops = __esm(() => {
|
|
|
214964
215128
|
init_sd_document_state();
|
|
214965
215129
|
init_text_offset_mapping();
|
|
214966
215130
|
init_paragraph_inline_model();
|
|
215131
|
+
init_compile_edit_text_inline_plan();
|
|
214967
215132
|
init_structural_boundary_map();
|
|
214968
215133
|
init_paragraph_section_collapse();
|
|
214969
215134
|
init_paragraph_delete_cell_boundary();
|
|
@@ -219917,15 +220082,31 @@ function canonicalizeCompareBodyRunXml(xml, referenceSteps) {
|
|
|
219917
220082
|
let result = "";
|
|
219918
220083
|
let cursor = 0;
|
|
219919
220084
|
for (const token of tokens) {
|
|
219920
|
-
const canonicalGap =
|
|
220085
|
+
const canonicalGap = canonicalizeProofingRunGap(xml.slice(cursor, token.start));
|
|
219921
220086
|
if (canonicalGap === null)
|
|
219922
220087
|
return null;
|
|
219923
220088
|
result += canonicalGap + token.xml;
|
|
219924
220089
|
cursor = token.end;
|
|
219925
220090
|
}
|
|
219926
|
-
const canonicalTail =
|
|
220091
|
+
const canonicalTail = canonicalizeProofingRunGap(xml.slice(cursor));
|
|
219927
220092
|
return canonicalTail === null ? null : result + canonicalTail;
|
|
219928
220093
|
}
|
|
220094
|
+
function canonicalizeProofingRunGap(xml) {
|
|
220095
|
+
const markerRe = /<(?:[A-Za-z_][\w.-]*:)?proofErr\b(?:[^>"']|"[^"]*"|'[^']*')*\/>/g;
|
|
220096
|
+
let result = "";
|
|
220097
|
+
let cursor = 0;
|
|
220098
|
+
for (const marker of xml.matchAll(markerRe)) {
|
|
220099
|
+
const index = marker.index ?? 0;
|
|
220100
|
+
const before = canonicalizeWordprocessingReplayXml(xml.slice(cursor, index));
|
|
220101
|
+
const canonicalMarker = canonicalizeWordprocessingReplayXml(marker[0]);
|
|
220102
|
+
if (before === null || canonicalMarker === null)
|
|
220103
|
+
return null;
|
|
220104
|
+
result += before + canonicalMarker;
|
|
220105
|
+
cursor = index + marker[0].length;
|
|
220106
|
+
}
|
|
220107
|
+
const trailing = canonicalizeWordprocessingReplayXml(xml.slice(cursor));
|
|
220108
|
+
return trailing === null ? null : result + trailing;
|
|
220109
|
+
}
|
|
219929
220110
|
function collectProtectedReferenceTokens(xml, referenceSteps) {
|
|
219930
220111
|
const tokens = [];
|
|
219931
220112
|
for (let index = 0;index < referenceSteps.length; index += 1) {
|
|
@@ -220731,6 +220912,26 @@ function runComparePayloadInsertCommit(input, storyId, step2, changeMode, option
|
|
|
220731
220912
|
});
|
|
220732
220913
|
return withParagraphInsertionCatalogRefs(input, receipt2, paragraph.wordIds, storyId);
|
|
220733
220914
|
}
|
|
220915
|
+
function unchangedBookmarkReferenceSteps(oldRuns, targetRuns) {
|
|
220916
|
+
const oldHasMarker = /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(oldRuns);
|
|
220917
|
+
const targetHasMarker = /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(targetRuns);
|
|
220918
|
+
if (!oldHasMarker && !targetHasMarker)
|
|
220919
|
+
return [];
|
|
220920
|
+
const oldBookmark = preservedBookmarkRunTokens(oldRuns);
|
|
220921
|
+
const targetBookmark = preservedBookmarkRunTokens(targetRuns);
|
|
220922
|
+
if (!oldBookmark || !targetBookmark || oldBookmark.startXml !== targetBookmark.startXml || oldBookmark.endXml !== targetBookmark.endXml || oldBookmark.leadingXml !== targetBookmark.leadingXml || oldBookmark.trailingXml !== targetBookmark.trailingXml)
|
|
220923
|
+
return null;
|
|
220924
|
+
const startBindings = replayFragmentNamespaceBindings(oldBookmark.startXml);
|
|
220925
|
+
const endBindings = replayFragmentNamespaceBindings(oldBookmark.endXml);
|
|
220926
|
+
const bookmarkBindings = { ...startBindings, ...endBindings };
|
|
220927
|
+
return [{
|
|
220928
|
+
kind: "bookmark-start",
|
|
220929
|
+
beforeXml: oldBookmark.startXml,
|
|
220930
|
+
afterXml: oldBookmark.startXml,
|
|
220931
|
+
beforeNamespaceBindings: bookmarkBindings,
|
|
220932
|
+
afterNamespaceBindings: bookmarkBindings
|
|
220933
|
+
}];
|
|
220934
|
+
}
|
|
220734
220935
|
function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pushHistory, referenceSteps) {
|
|
220735
220936
|
const { state, txId } = input;
|
|
220736
220937
|
const partUri = storyPartUriFromStoryId2(storyId);
|
|
@@ -220748,6 +220949,14 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
|
|
|
220748
220949
|
const pPrXml = findFirstElement(paraXml, "pPr")?.xml ?? "";
|
|
220749
220950
|
const targetParagraphPropertiesXml = step2.targetParagraphPropertiesXml === undefined ? undefined : rewriteCanonicalWordprocessingPrefix(step2.targetParagraphPropertiesXml, paragraphWrapper.wordprocessingPrefix);
|
|
220750
220951
|
const newRuns = rewriteCanonicalWordprocessingPrefix(step2.targetRunXml ?? renderParagraphRuns(step2.text), paragraphWrapper.wordprocessingPrefix);
|
|
220952
|
+
const openEnd = paragraphWrapper.contentStart;
|
|
220953
|
+
const closeStart = paraXml.lastIndexOf("</");
|
|
220954
|
+
const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
|
|
220955
|
+
const oldRunsRaw = stripElements(innerXml, "pPr");
|
|
220956
|
+
const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, newRuns);
|
|
220957
|
+
if (stableBookmarkSteps === null && referenceSteps.length === 0)
|
|
220958
|
+
return rejected14(txId, "unsupported-context");
|
|
220959
|
+
const protectedReferenceSteps = [...referenceSteps, ...stableBookmarkSteps ?? []];
|
|
220751
220960
|
let newParaXml;
|
|
220752
220961
|
const createdRefs = [];
|
|
220753
220962
|
if (changeMode === "tracked") {
|
|
@@ -220763,12 +220972,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
|
|
|
220763
220972
|
storyId
|
|
220764
220973
|
});
|
|
220765
220974
|
}
|
|
220766
|
-
const openEnd = paragraphWrapper.contentStart;
|
|
220767
|
-
const closeStart = paraXml.lastIndexOf("</");
|
|
220768
|
-
const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
|
|
220769
|
-
const oldRunsRaw = stripElements(innerXml, "pPr");
|
|
220770
220975
|
const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
|
|
220771
|
-
const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns,
|
|
220976
|
+
const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns, protectedReferenceSteps, stamps, paragraphWrapper.wordprocessingPrefix);
|
|
220977
|
+
if (!protectedRuns && stableBookmarkSteps?.length)
|
|
220978
|
+
return rejected14(txId, "unsupported-context");
|
|
220772
220979
|
const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
|
|
220773
220980
|
const insXml = protectedRuns ? "" : newRuns ? wrapTracked("ins", newRuns, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
|
|
220774
220981
|
const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
|
|
@@ -220852,6 +221059,10 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
|
|
|
220852
221059
|
const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
|
|
220853
221060
|
const oldRunsRaw = stripElements(innerXml, "pPr");
|
|
220854
221061
|
const paragraphPropertiesChanged = !equivalentParagraphProperties(targetPPrXml, pPrXml);
|
|
221062
|
+
const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, targetRunXml);
|
|
221063
|
+
if (stableBookmarkSteps === null && referenceSteps.length === 0)
|
|
221064
|
+
return rejected14(txId, "unsupported-context");
|
|
221065
|
+
const protectedReferenceSteps = [...referenceSteps, ...stableBookmarkSteps ?? []];
|
|
220855
221066
|
const baseSimpleRuns = scanSimpleRunFormatting(oldRunsRaw);
|
|
220856
221067
|
const targetSimpleRuns = scanSimpleRunFormatting(targetRunXml);
|
|
220857
221068
|
const paragraphPropertiesOnly = paragraphPropertiesChanged && baseSimpleRuns?.text === targetSimpleRuns?.text && computeRunSignature(targetRunXml) === computeRunSignature(oldRunsRaw);
|
|
@@ -220915,7 +221126,9 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
|
|
|
220915
221126
|
if (!stamps)
|
|
220916
221127
|
return rejected14(txId, "no-author-configured");
|
|
220917
221128
|
const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
|
|
220918
|
-
const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml,
|
|
221129
|
+
const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml, protectedReferenceSteps, stamps, paragraphWrapper.wordprocessingPrefix);
|
|
221130
|
+
if (!protectedRuns && stableBookmarkSteps?.length)
|
|
221131
|
+
return rejected14(txId, "unsupported-context");
|
|
220919
221132
|
const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
|
|
220920
221133
|
const insXml = protectedRuns ? "" : targetRunXml ? wrapTracked("ins", targetRunXml, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
|
|
220921
221134
|
if (delXml || insXml) {
|
|
@@ -239364,7 +239577,7 @@ function toRoman(ordinal) {
|
|
|
239364
239577
|
}
|
|
239365
239578
|
function extractParagraphText(paraXml) {
|
|
239366
239579
|
let out = "";
|
|
239367
|
-
for (const match of paraXml.matchAll(/<[\w.-]+:t\b[^>]
|
|
239580
|
+
for (const match of paraXml.matchAll(/<[\w.-]+:t\b[^>]*?(?<!\/)>([\s\S]*?)<\/[\w.-]+:t>/g)) {
|
|
239368
239581
|
out += decodeXmlText(match[1] ?? "");
|
|
239369
239582
|
}
|
|
239370
239583
|
return out;
|
|
@@ -246913,7 +247126,7 @@ function prepareHistoryReplayMutation(state, entry, direction, patchGroup) {
|
|
|
246913
247126
|
...contentControlRewrite.addedBlockIds,
|
|
246914
247127
|
...contentControlRewrite.contentBlockIds,
|
|
246915
247128
|
...contentControlRewrite.leadingBlockIds
|
|
246916
|
-
])] : collectPatchGroupTargetBlockIds(patchGroup);
|
|
247129
|
+
])] : patchGroup.source.kind === "compareApply" ? [...new Set(patchGroup.source.bodySteps.map((step2) => step2.blockId))] : collectPatchGroupTargetBlockIds(patchGroup);
|
|
246917
247130
|
const currentBaseRevisions = {
|
|
246918
247131
|
package: state.packageRevision,
|
|
246919
247132
|
perPart: {}
|
|
@@ -247167,6 +247380,8 @@ function collectPatchGroupTargetBlockIds(patchGroup) {
|
|
|
247167
247380
|
return [...blockIds];
|
|
247168
247381
|
}
|
|
247169
247382
|
function inferHistoryStorySurfaceFamily(sourceKind) {
|
|
247383
|
+
if (sourceKind === "compareApply")
|
|
247384
|
+
return "compareApply";
|
|
247170
247385
|
if (sourceKind === "editText")
|
|
247171
247386
|
return "storyText";
|
|
247172
247387
|
if (sourceKind.startsWith("list"))
|
|
@@ -251364,7 +251579,7 @@ var init_operation_definitions2 = __esm(() => {
|
|
|
251364
251579
|
},
|
|
251365
251580
|
get_content: {
|
|
251366
251581
|
toolName: "superdoc_get_content",
|
|
251367
|
-
description: "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. " + 'Action "blocks" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. ' + 'When you need to evaluate or rewrite existing paragraphs or clauses, prefer action "blocks" with includeText:true so you can identify the correct block and then target it by nodeId. ' + 'Actions "text", "markdown", and "html" return compact strings. Actions "markdown_projection" and "html_projection" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. ' + "Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. " + 'Action "info" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. ' + 'The "blocks" action supports pagination via "offset" and "limit", filtering via "nodeTypes", and numbering projection via "reviewMode". Other actions ignore pagination and filtering parameters. ' + "This tool never modifies the document. " + "Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.",
|
|
251582
|
+
description: "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. " + 'Action "blocks" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Paragraph-class blocks include tabCount, the number of U+0009 tabs in the complete text even if the 80-character preview trims or truncates them. If tabCount is positive, read includeText:true before editing; do not treat a preview space as proof that there is no tab. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. ' + 'When you need to evaluate or rewrite existing paragraphs or clauses, prefer action "blocks" with includeText:true so you can identify the correct block and then target it by nodeId. ' + 'Actions "text", "markdown", and "html" return compact strings. Actions "markdown_projection" and "html_projection" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. ' + "Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. " + 'Action "info" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. ' + 'The "blocks" action supports pagination via "offset" and "limit", filtering via "nodeTypes", and numbering projection via "reviewMode". Other actions ignore pagination and filtering parameters. ' + "This tool never modifies the document. " + "Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.",
|
|
251368
251583
|
inputExamples: [
|
|
251369
251584
|
{ action: "blocks" },
|
|
251370
251585
|
{ action: "blocks", includeText: true, offset: 0, limit: 20, reviewMode: "final" },
|
|
@@ -251656,7 +251871,7 @@ Complete new body.`,
|
|
|
251656
251871
|
section: { toolName: "superdoc_section", description: "Page layout, margins, columns" },
|
|
251657
251872
|
mutations: {
|
|
251658
251873
|
toolName: "superdoc_mutations",
|
|
251659
|
-
description: "All steps succeed or all fail; no partial application. " + "Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. " + "Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. " + 'Each step has an id, an op, a "where" clause for targeting ({by:"select", select:{...}, require:"first"|"exactlyOne"|"all"} or {by:"ref", ref:"..."} or {by:"block", nodeType:"paragraph", nodeId:"..."}), and "args" with operation-specific parameters. ' + 'Use {by:"block", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action "blocks" without relying on text matching. ' + 'For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:"blocks" and includeText:true, then rewrite the matching block by nodeId. ' + 'Use {by:"select"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. ' + 'For create steps, "where" targets an existing anchor block and args.position ("before" or "after") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. ' + 'For format.apply with require "all", use a node selector to format every heading or paragraph at once: {by:"select", select:{type:"node", nodeType:"heading"}, require:"all"}. ' + "Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. " + 'Action "preview" dry-runs the plan. Action "apply" executes it. ' + "If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. " + "Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.",
|
|
251874
|
+
description: "All steps succeed or all fail; no partial application. " + "Execute multiple operations atomically in one batch. Use this for any workflow needing 2+ changes. " + "Supported step types: text (text.rewrite, text.insert, text.delete), format (format.apply), create (create.heading, create.paragraph, create.table), assert. " + 'Each step has an id, an op, a "where" clause for targeting ({by:"select", select:{...}, require:"first"|"exactlyOne"|"all"} or {by:"ref", ref:"..."} or {by:"block", nodeType:"paragraph", nodeId:"..."}), and "args" with operation-specific parameters. ' + 'Use {by:"block", nodeType, nodeId} when you want to rewrite, delete, format, or anchor against a whole known block from superdoc_get_content action "blocks" without relying on text matching. ' + 'For full-paragraph or full-clause rewrites, first call superdoc_get_content with action:"blocks" and includeText:true, then rewrite the matching block by nodeId. ' + 'For a placeholder or name within a tab-separated paragraph, use a text.rewrite where.by:"select" targeting only the exact placeholder; a whole-block plain-text rewrite omitting tabs deletes those controls. ' + 'Use {by:"select"} only for substring edits, discovery, or insertion relative to a sentence fragment; do NOT use a shortened text selector to replace an entire known block. ' + 'For create steps, "where" targets an existing anchor block and args.position ("before" or "after") controls placement. Sequential creates targeting the same anchor maintain correct order via internal position mapping. ' + 'For format.apply with require "all", use a node selector to format every heading or paragraph at once: {by:"select", select:{type:"node", nodeType:"heading"}, require:"all"}. ' + "Selectors resolve at compile time (before execution). This means format.apply steps CANNOT target content created by earlier create steps in the same batch. Split creates and formatting into separate batches: first a mutations call with creates, then a mutations call with format.apply. " + 'Action "preview" dry-runs the plan. Action "apply" executes it. ' + "If a selector matches nothing, the failure reports the step id plus selector details so you can retry with a shorter or more distinctive anchor. " + "Do NOT create two steps that target overlapping text in the same block; combine them into a single text.rewrite step.",
|
|
251660
251875
|
inputExamples: [
|
|
251661
251876
|
{
|
|
251662
251877
|
action: "apply",
|
|
@@ -262080,6 +262295,11 @@ var init_schemas5 = __esm(() => {
|
|
|
262080
262295
|
oneOf: [{ type: "string" }, { type: "null" }],
|
|
262081
262296
|
description: "Full flattened block text when requested with includeText."
|
|
262082
262297
|
},
|
|
262298
|
+
tabCount: {
|
|
262299
|
+
type: "integer",
|
|
262300
|
+
minimum: 0,
|
|
262301
|
+
description: "Tabs in complete paragraph text, even beyond the preview."
|
|
262302
|
+
},
|
|
262083
262303
|
isEmpty: { type: "boolean" },
|
|
262084
262304
|
styleId: { oneOf: [{ type: "string" }, { type: "null" }], description: "Named paragraph style." },
|
|
262085
262305
|
fontFamily: { type: "string", description: "Font family from first text run." },
|
|
@@ -280493,12 +280713,12 @@ function wrapRangeWithMarkupInParagraphXml(input) {
|
|
|
280493
280713
|
const middleText = run.text.slice(sliceStart, sliceEnd);
|
|
280494
280714
|
const afterText = run.text.slice(sliceEnd);
|
|
280495
280715
|
if (beforeText.length > 0)
|
|
280496
|
-
beforeSegment.push(renderRun(run.kind, run.prefix, beforeText, run.rPr, run.leafXml));
|
|
280716
|
+
beforeSegment.push(renderRun(run.kind, run.prefix, beforeText, run.rPr, run.leafXml, run.open));
|
|
280497
280717
|
if (middleText.length > 0) {
|
|
280498
|
-
wrappedRuns.push(renderRun(run.kind, run.prefix, middleText, run.rPr, run.leafXml));
|
|
280718
|
+
wrappedRuns.push(renderRun(run.kind, run.prefix, middleText, run.rPr, run.leafXml, run.open));
|
|
280499
280719
|
}
|
|
280500
280720
|
if (afterText.length > 0)
|
|
280501
|
-
afterSegment.push(renderRun(run.kind, run.prefix, afterText, run.rPr, run.leafXml));
|
|
280721
|
+
afterSegment.push(renderRun(run.kind, run.prefix, afterText, run.rPr, run.leafXml, run.open));
|
|
280502
280722
|
segmentCursor = run.xmlEnd;
|
|
280503
280723
|
}
|
|
280504
280724
|
if (wrappedRuns.length === 0) {
|
|
@@ -280528,6 +280748,8 @@ function replaceRangeInParagraphXml(input) {
|
|
|
280528
280748
|
const gapXml = input.paragraphXml.slice(segmentCursor, run.xmlStart);
|
|
280529
280749
|
if (index === span.value.firstRunIdx)
|
|
280530
280750
|
beforeSegment.push(gapXml);
|
|
280751
|
+
else if (gapXml.trim())
|
|
280752
|
+
return { ok: false, reason: "unsupported-context" };
|
|
280531
280753
|
}
|
|
280532
280754
|
const sliceStart = index === span.value.firstRunIdx ? span.value.startInFirstRun : 0;
|
|
280533
280755
|
const sliceEnd = index === span.value.lastRunIdx ? span.value.endInLastRun : run.text.length;
|
|
@@ -280998,6 +281220,7 @@ function parsePlainRun2(runXml, textStart, xmlStart, xmlEnd) {
|
|
|
280998
281220
|
xmlStart,
|
|
280999
281221
|
xmlEnd,
|
|
281000
281222
|
xml: runXml,
|
|
281223
|
+
open: run.open,
|
|
281001
281224
|
prefix: run.prefix,
|
|
281002
281225
|
textStart,
|
|
281003
281226
|
textEnd: textStart + text.length,
|
|
@@ -281334,15 +281557,15 @@ function buildRPrChange(prefix, stamp, previousChildren) {
|
|
|
281334
281557
|
const previous = `<${prefix}:rPr>${serializeTopLevelChildren(previousChildren)}</${prefix}:rPr>`;
|
|
281335
281558
|
return `<${prefix}:rPrChange w:id="${stamp.revisionId}" w:author="${escapeXmlAttribute3(stamp.author.name)}"${initials} w:date="${escapeXmlAttribute3(stamp.date)}">${previous}</${prefix}:rPrChange>`;
|
|
281336
281559
|
}
|
|
281337
|
-
function renderRun(kind, prefix, text, rPrXml, leafXml) {
|
|
281560
|
+
function renderRun(kind, prefix, text, rPrXml, leafXml, runOpen = `<${prefix}:r>`) {
|
|
281338
281561
|
if (kind !== "text") {
|
|
281339
281562
|
if (text.length === 0)
|
|
281340
281563
|
return "";
|
|
281341
281564
|
const fallbackLeaf = kind === "tab" ? `<${prefix}:tab/>` : `<${prefix}:${kind}/>`;
|
|
281342
|
-
return
|
|
281565
|
+
return `${runOpen}${rPrXml}${leafXml ?? fallbackLeaf}</${prefix}:r>`;
|
|
281343
281566
|
}
|
|
281344
281567
|
const preserve = /^\s|\s$/.test(text) ? ' xml:space="preserve"' : "";
|
|
281345
|
-
return
|
|
281568
|
+
return `${runOpen}${rPrXml}<${prefix}:t${preserve}>${escapeXmlText3(text)}</${prefix}:t></${prefix}:r>`;
|
|
281346
281569
|
}
|
|
281347
281570
|
function ensureHyperlinkRunStyle2(rPrXml, fallbackPrefix, styleId = "Hyperlink") {
|
|
281348
281571
|
const escapedStyleId = escapeXmlAttribute3(styleId);
|
|
@@ -285282,6 +285505,9 @@ function createParagraphIdBatchAllocator(context, count) {
|
|
|
285282
285505
|
function collectPackageParaIds(context) {
|
|
285283
285506
|
const used = new Set;
|
|
285284
285507
|
for (const partUri of listSDDocumentSessionInternalPartUris(context.session)) {
|
|
285508
|
+
const contentType = getSDDocumentSessionInternalPartDescriptor(context.session, partUri)?.contentType?.toLowerCase();
|
|
285509
|
+
if (!partUri.toLowerCase().endsWith(".xml") && !contentType?.endsWith("+xml") && contentType !== "application/xml")
|
|
285510
|
+
continue;
|
|
285285
285511
|
const bytes = getSDDocumentSessionInternalPartBytes(context.session, partUri);
|
|
285286
285512
|
if (!bytes)
|
|
285287
285513
|
continue;
|
|
@@ -302565,11 +302791,16 @@ function projectTableListEntry(ordinal, nodeId, text, includeText) {
|
|
|
302565
302791
|
}
|
|
302566
302792
|
function projectParagraphListEntry(input) {
|
|
302567
302793
|
const trimmed = input.text.trim();
|
|
302794
|
+
let tabCount = 0;
|
|
302795
|
+
for (let position = input.text.indexOf("\t");position !== -1; position = input.text.indexOf("\t", position + 1)) {
|
|
302796
|
+
tabCount++;
|
|
302797
|
+
}
|
|
302568
302798
|
const item = {
|
|
302569
302799
|
ordinal: input.ordinal,
|
|
302570
302800
|
nodeId: input.nodeId,
|
|
302571
302801
|
nodeType: input.nodeType,
|
|
302572
302802
|
textPreview: trimmed.length > 80 ? `${trimmed.slice(0, 77)}…` : trimmed,
|
|
302803
|
+
tabCount,
|
|
302573
302804
|
isEmpty: trimmed.length === 0
|
|
302574
302805
|
};
|
|
302575
302806
|
if (input.styleId)
|
|
@@ -328985,7 +329216,7 @@ class V2ContentControlsAdapter {
|
|
|
328985
329216
|
}
|
|
328986
329217
|
setTextValue(input, options) {
|
|
328987
329218
|
const loaded = this.load();
|
|
328988
|
-
const control = this.requireBodyControl(input.target, loaded);
|
|
329219
|
+
const control = options?.changeMode === "tracked" ? this.requireBodyControl(input.target, loaded) : this.requireControl(input.target, loaded);
|
|
328989
329220
|
if (control.info.controlType !== "text") {
|
|
328990
329221
|
throw operationError("TYPE_MISMATCH", `contentControls.text.setValue requires control type text, but found "${control.info.controlType}".`);
|
|
328991
329222
|
}
|
|
@@ -329005,9 +329236,14 @@ class V2ContentControlsAdapter {
|
|
|
329005
329236
|
}
|
|
329006
329237
|
if (dryRunRequested(input, options))
|
|
329007
329238
|
return this.validateDryRun(input, options, control.target);
|
|
329239
|
+
const part = loaded.parts.find((candidate2) => candidate2.storyId === control.storyId);
|
|
329008
329240
|
const replacement = replaceSdtContentXml(control, buildTextReplacementContentXml(value2, control.info.kind, createParaIdAllocator(this.context), control.contentXml, false));
|
|
329009
|
-
const nextXml = replaceRange2(
|
|
329010
|
-
return this.commitDocument(nextXml, "content-control-replace-content", input, options, control.target
|
|
329241
|
+
const nextXml = replaceRange2(part.xml, control.start, control.end, replacement);
|
|
329242
|
+
return this.commitDocument(nextXml, "content-control-replace-content", input, options, control.target, {
|
|
329243
|
+
partUri: part.partUri,
|
|
329244
|
+
storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
|
|
329245
|
+
preserveRenderCommit: this.context.isCollaborativeSession()
|
|
329246
|
+
});
|
|
329011
329247
|
}
|
|
329012
329248
|
setDateValue(input, options) {
|
|
329013
329249
|
const loaded = this.load();
|
|
@@ -329228,12 +329464,14 @@ class V2ContentControlsAdapter {
|
|
|
329228
329464
|
}
|
|
329229
329465
|
mutateControl(target, input, options, transform2, prefix = "content-control-mutate", validate) {
|
|
329230
329466
|
const loaded = this.load();
|
|
329231
|
-
const control = this.requireBodyControl(target, loaded);
|
|
329232
|
-
validate?.(control, loaded);
|
|
329233
329467
|
const tracked = options?.changeMode === "tracked";
|
|
329468
|
+
const storyAware = prefix === "content-control-pr" || prefix === "content-control-unwrap";
|
|
329469
|
+
const control = tracked || !storyAware ? this.requireBodyControl(target, loaded) : this.requireControl(target, loaded);
|
|
329470
|
+
const part = loaded.parts.find((candidate2) => candidate2.storyId === control.storyId);
|
|
329471
|
+
validate?.(control, loaded);
|
|
329234
329472
|
if (tracked) {
|
|
329235
329473
|
this.validateTrackedControlMutation(input, options);
|
|
329236
|
-
if (hasTrackedControlAncestor(
|
|
329474
|
+
if (hasTrackedControlAncestor(part.xml, control) || !["content-control-delete", "content-control-unwrap", "content-control-repeat-delete", "content-control-pr"].includes(prefix)) {
|
|
329237
329475
|
this.requireDirectControlStructure(input, options);
|
|
329238
329476
|
}
|
|
329239
329477
|
}
|
|
@@ -329246,12 +329484,12 @@ class V2ContentControlsAdapter {
|
|
|
329246
329484
|
let replacement = typeof transformed === "string" ? transformed : transformed.xml;
|
|
329247
329485
|
let createdRefs = typeof transformed === "string" ? undefined : transformed.createdRefs;
|
|
329248
329486
|
if (tracked && typeof transformed === "string") {
|
|
329249
|
-
const namespaces = collectXmlElementRanges(
|
|
329487
|
+
const namespaces = collectXmlElementRanges(part.xml).ranges.find((range) => range.start === control.start)?.namespaceBindings;
|
|
329250
329488
|
const prepared = prepareTrackedContentControlXml({
|
|
329251
329489
|
context: this.context,
|
|
329252
329490
|
beforeXml: control.xml,
|
|
329253
329491
|
afterXml: replacement,
|
|
329254
|
-
kind: trackedControlPlacement(
|
|
329492
|
+
kind: trackedControlPlacement(part.xml, control),
|
|
329255
329493
|
ownership: prefix === "content-control-unwrap" || prefix === "content-control-repeat-delete",
|
|
329256
329494
|
namespaceBindings: new Map(Object.entries(namespaces ?? {})),
|
|
329257
329495
|
expectedRevision: expectedRevisionFrom(input, options),
|
|
@@ -329262,8 +329500,13 @@ class V2ContentControlsAdapter {
|
|
|
329262
329500
|
replacement = prepared.xml;
|
|
329263
329501
|
createdRefs = prepared.wordIds.map((entityId) => ({ kind: "trackedChange", entityId, storyId: control.storyId }));
|
|
329264
329502
|
}
|
|
329265
|
-
const nextXml = replaceRange2(
|
|
329266
|
-
return this.commitDocument(nextXml, prefix, input, options, control.target, {
|
|
329503
|
+
const nextXml = replaceRange2(part.xml, control.start, control.end, replacement);
|
|
329504
|
+
return this.commitDocument(nextXml, prefix, input, options, control.target, {
|
|
329505
|
+
partUri: part.partUri,
|
|
329506
|
+
storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
|
|
329507
|
+
preserveRenderCommit: this.context.isCollaborativeSession(),
|
|
329508
|
+
createdRefs
|
|
329509
|
+
});
|
|
329267
329510
|
}
|
|
329268
329511
|
insertRepeatingItem(input, options, insertIndex) {
|
|
329269
329512
|
this.validateTrackedControlMutation(input, options);
|
|
@@ -331068,7 +331311,7 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
|
|
|
331068
331311
|
}
|
|
331069
331312
|
};
|
|
331070
331313
|
}
|
|
331071
|
-
if (kind === "inline" && !hasReplacementContent
|
|
331314
|
+
if (kind === "inline" && !hasReplacementContent) {
|
|
331072
331315
|
const template = splitSdtTemplateAroundContent(sdtXml);
|
|
331073
331316
|
if (!template) {
|
|
331074
331317
|
return {
|
|
@@ -331089,6 +331332,18 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
|
|
|
331089
331332
|
if (wrappedRuns.ok) {
|
|
331090
331333
|
return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, wrappedRuns.xml) };
|
|
331091
331334
|
}
|
|
331335
|
+
return { ok: false, failure: { code: "CAPABILITY_UNAVAILABLE", message: "Content-control selection spans unsupported inline structures." } };
|
|
331336
|
+
}
|
|
331337
|
+
if (kind === "inline" && hasReplacementContent) {
|
|
331338
|
+
const replaced = replaceRangeInParagraphXml({
|
|
331339
|
+
paragraphXml: para.xml,
|
|
331340
|
+
rangeStart: target.start.offset,
|
|
331341
|
+
rangeEnd: target.end.offset,
|
|
331342
|
+
replacementXml: replaceSdtContentInTemplate(sdtXml, buildReplacementContentXml2(replacementContent))
|
|
331343
|
+
});
|
|
331344
|
+
if (replaced.ok) {
|
|
331345
|
+
return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, replaced.xml) };
|
|
331346
|
+
}
|
|
331092
331347
|
return {
|
|
331093
331348
|
ok: false,
|
|
331094
331349
|
failure: {
|
|
@@ -331105,15 +331360,6 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
|
|
|
331105
331360
|
return { ok: false, failure: { code: "CAPABILITY_UNAVAILABLE", message: "Content-control selection spans unsupported inline structures." } };
|
|
331106
331361
|
return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, wrapped) };
|
|
331107
331362
|
}
|
|
331108
|
-
function selectedTextRunCount(paragraphXml, start, end) {
|
|
331109
|
-
const runs = new Set;
|
|
331110
|
-
for (const piece of parseParagraphInlineMap(paragraphXml).leaves()) {
|
|
331111
|
-
if (piece.kind === "text" && piece.textRole === "visible" && piece.visibleStart < end && piece.visibleEnd > start) {
|
|
331112
|
-
runs.add(piece.runCharStart);
|
|
331113
|
-
}
|
|
331114
|
-
}
|
|
331115
|
-
return runs.size;
|
|
331116
|
-
}
|
|
331117
331363
|
function splitSdtTemplateAroundContent(sdtXml) {
|
|
331118
331364
|
const sdtRange = findFirstSdtElementRange(sdtXml);
|
|
331119
331365
|
if (!sdtRange)
|
|
@@ -393765,6 +394011,7 @@ function createHocuspocusSingleDocAdapter(config2) {
|
|
|
393765
394011
|
token: typeof config2.token === "string" || config2.token == null ? config2.token ?? null : config2.token,
|
|
393766
394012
|
parameters: config2.params ?? {},
|
|
393767
394013
|
preserveConnection: false,
|
|
394014
|
+
broadcast: config2.broadcast ?? true,
|
|
393768
394015
|
quiet: true,
|
|
393769
394016
|
onSynced() {
|
|
393770
394017
|
if (!hasSynced) {
|
|
@@ -407312,7 +407559,7 @@ function parseRun2(runXml, textTagLocalName = "t", inheritedNamespaceBindings =
|
|
|
407312
407559
|
atomKind: INLINE_ATOM_KIND.noteRef,
|
|
407313
407560
|
id: attrLocal2(next.openTagInner, "id"),
|
|
407314
407561
|
xml: next.xml,
|
|
407315
|
-
meta: { kind: local },
|
|
407562
|
+
meta: { kind: local, runAttributes: attributes },
|
|
407316
407563
|
visibleLength: 0
|
|
407317
407564
|
});
|
|
407318
407565
|
} else if (local === "sym" || local === "noBreakHyphen") {
|
|
@@ -407323,7 +407570,7 @@ function parseRun2(runXml, textTagLocalName = "t", inheritedNamespaceBindings =
|
|
|
407323
407570
|
atomKind: INLINE_ATOM_KIND.preserved,
|
|
407324
407571
|
id: null,
|
|
407325
407572
|
xml: next.xml,
|
|
407326
|
-
meta: { tag: local, container: "run-child" },
|
|
407573
|
+
meta: { tag: local, container: "run-child", runAttributes: attributes },
|
|
407327
407574
|
visibleLength: 0
|
|
407328
407575
|
});
|
|
407329
407576
|
}
|
|
@@ -420555,7 +420802,9 @@ function serializeBlockXml(block, extraAtoms = [], context = { inherited: CANONI
|
|
|
420555
420802
|
const atomXml = atom.kind === "synthetic-comment-marker" ? `<${w}:${atom.meta.marker} ${w}:id="${xmlEscape(String(atom.meta.commentId))}"/>` : atom.xml;
|
|
420556
420803
|
const attributedBreakXml = runBackedAttributedBreakXml(atom);
|
|
420557
420804
|
if (atomEmissionMode(atom) === "run-child") {
|
|
420558
|
-
|
|
420805
|
+
const atomRunAttributes = atom.meta.runAttributes;
|
|
420806
|
+
const attributes = atomRunAttributes && typeof atomRunAttributes === "object" && !Array.isArray(atomRunAttributes) ? atomRunAttributes : runAttributes;
|
|
420807
|
+
sb.push(serializeInlineRunAtom(attributedBreakXml ?? atomXml, attributes, w));
|
|
420559
420808
|
} else {
|
|
420560
420809
|
sb.push(atomXml);
|
|
420561
420810
|
}
|
|
@@ -424846,7 +425095,7 @@ function hasStrictMirrorPrerequisites(prepared, options) {
|
|
|
424846
425095
|
case "storyAnchor":
|
|
424847
425096
|
return options.session != null;
|
|
424848
425097
|
case "compareApply":
|
|
424849
|
-
return
|
|
425098
|
+
return options.session != null;
|
|
424850
425099
|
default: {
|
|
424851
425100
|
const exhaustive = extension2.family;
|
|
424852
425101
|
return exhaustive;
|
|
@@ -424944,13 +425193,24 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, tracked
|
|
|
424944
425193
|
return mirrorPreparedTrackedDecide(prepared, trackedDecision);
|
|
424945
425194
|
}
|
|
424946
425195
|
if (extension2.family === "compareApply") {
|
|
424947
|
-
|
|
424948
|
-
|
|
424949
|
-
|
|
424950
|
-
|
|
424951
|
-
|
|
424952
|
-
|
|
424953
|
-
|
|
425196
|
+
if (!options.session) {
|
|
425197
|
+
return {
|
|
425198
|
+
mirrored: false,
|
|
425199
|
+
mirrorPath: "session-sync",
|
|
425200
|
+
failure: {
|
|
425201
|
+
storyId: prepared.resolvedTargets.stories[0] ?? "",
|
|
425202
|
+
message: "compareApply session sync requires an authoritative session"
|
|
425203
|
+
}
|
|
425204
|
+
};
|
|
425205
|
+
}
|
|
425206
|
+
const sessionSync = mirrorStorySurfaceFromSession({
|
|
425207
|
+
session: options.session,
|
|
425208
|
+
prepared,
|
|
425209
|
+
extension: extension2,
|
|
425210
|
+
storyIds: storyIdsRequiringShards(prepared, extension2),
|
|
425211
|
+
resolveStoryShard: options.resolveStoryShard
|
|
425212
|
+
});
|
|
425213
|
+
return { ...sessionSync, mirrorPath: "session-sync" };
|
|
424954
425214
|
}
|
|
424955
425215
|
if (extension2.family === "storyAnchor" && prepared.source.kind === "insertComment" && !prepared.source.materialize) {
|
|
424956
425216
|
return mirrorPreparedCommentInsert(prepared, extension2, options);
|
|
@@ -425718,6 +425978,9 @@ function admitPreparedStorySurfaceMutation(prepared, options) {
|
|
|
425718
425978
|
}
|
|
425719
425979
|
if (!touchesOwnedStoryPart(prepared))
|
|
425720
425980
|
return { ok: true };
|
|
425981
|
+
if (extension2.family === "compareApply") {
|
|
425982
|
+
return validateCompareApplySessionSync(prepared, extension2, options);
|
|
425983
|
+
}
|
|
425721
425984
|
if (extension2.family === "storyText") {
|
|
425722
425985
|
if (extension2.historyReplay || extension2.resyncFromSession || extension2.sessionSync) {
|
|
425723
425986
|
return validateStoryTextSessionSync(prepared, extension2, options);
|
|
@@ -425786,6 +426049,32 @@ function admitPreparedStorySurfaceMutation(prepared, options) {
|
|
|
425786
426049
|
}
|
|
425787
426050
|
return { ok: true };
|
|
425788
426051
|
}
|
|
426052
|
+
function validateCompareApplySessionSync(prepared, extension2, options) {
|
|
426053
|
+
const source = prepared.source;
|
|
426054
|
+
if (source.kind !== "compareApply" || !options.session) {
|
|
426055
|
+
return { ok: false, message: "compareApply session sync requires an authoritative session" };
|
|
426056
|
+
}
|
|
426057
|
+
if (options.isSessionProjectionCurrent?.() !== true) {
|
|
426058
|
+
return { ok: false, message: "compareApply requires a current collaborative session projection" };
|
|
426059
|
+
}
|
|
426060
|
+
const storyId = String(source.storyId);
|
|
426061
|
+
const ownership = prepared.resolvedTargets.storyPartOwnership;
|
|
426062
|
+
if (!extension2.storyLocal || prepared.resolvedTargets.stories.length !== 1 || String(prepared.resolvedTargets.stories[0]) !== storyId || ownership.length !== 1 || String(ownership[0]?.storyId) !== storyId || prepared.resolvedTargets.partUris.length !== 1 || String(prepared.resolvedTargets.partUris[0]) !== String(ownership[0]?.partUri)) {
|
|
426063
|
+
return { ok: false, message: "compareApply collaboration requires one owned story part" };
|
|
426064
|
+
}
|
|
426065
|
+
if (source.bodySteps.length === 0 || source.bodySteps.some((step3) => step3.kind !== "edit") || source.storyGroups?.length || source.storyPackageOperations?.length || source.commentSteps?.length || source.packageRewrites?.length || source.relationshipBackedBodyRewrites?.length || source.headerFooterLifecycle || source.headerFooterSlotSteps?.length || source.tableTopologySteps?.length || source.tableBlockSteps?.length || source.tablePropertySteps?.length || source.sectionReplaySteps?.length || source.referenceReplaySteps?.length) {
|
|
426066
|
+
return { ok: false, message: "compareApply collaboration supports paragraph text edits only" };
|
|
426067
|
+
}
|
|
426068
|
+
const targetBlockIds2 = [...new Set(source.bodySteps.map((step3) => step3.blockId))];
|
|
426069
|
+
if (targetBlockIds2.length !== extension2.targetBlockIds.length || targetBlockIds2.some((blockId) => !extension2.targetBlockIds.includes(blockId))) {
|
|
426070
|
+
return { ok: false, message: "compareApply target blocks do not match its prepared refresh scope" };
|
|
426071
|
+
}
|
|
426072
|
+
const shard = options.resolveStoryShard(storyId);
|
|
426073
|
+
if (!shard || targetBlockIds2.some((blockId) => !findBlockMap(shard, blockId))) {
|
|
426074
|
+
return { ok: false, message: "compareApply target blocks are missing from the story shard" };
|
|
426075
|
+
}
|
|
426076
|
+
return { ok: true };
|
|
426077
|
+
}
|
|
425789
426078
|
function validateStoryTextSessionSync(prepared, extension2, options) {
|
|
425790
426079
|
if (!options.session) {
|
|
425791
426080
|
return { ok: false, message: "storyText session sync requires an authoritative session" };
|
|
@@ -427422,6 +427711,7 @@ function createCollabV2SessionProjectionController(options) {
|
|
|
427422
427711
|
const storyBackend = createStorySurfaceExecutionBackend({
|
|
427423
427712
|
delegate: packageBackend,
|
|
427424
427713
|
session: options.session,
|
|
427714
|
+
isSessionProjectionCurrent: () => !destroyed && !remoteProjectionPending && !deferredSessionAuthoritativeRemotePending && sessionStoryAlignment === "aligned",
|
|
427425
427715
|
resolveStoryShard(storyId) {
|
|
427426
427716
|
const handle = options.dispatcherRegistry.findStoryShardByStoryId?.(storyId);
|
|
427427
427717
|
return handle ? collabUnitTargetOrDoc(handle) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/mcp",
|
|
3
|
-
"version": "1.2.0-next.
|
|
3
|
+
"version": "1.2.0-next.10",
|
|
4
4
|
"description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
27
|
-
"@superdoc/sdk": "2.15.0-next.
|
|
27
|
+
"@superdoc/sdk": "2.15.0-next.10",
|
|
28
28
|
"debug": "^4.4.3",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"superdoc": "2.18.0-next.
|
|
33
|
-
"@superdoc/docx-engine": "0.17.0-next.
|
|
32
|
+
"superdoc": "2.18.0-next.10",
|
|
33
|
+
"@superdoc/docx-engine": "0.17.0-next.12",
|
|
34
34
|
"@superdoc/document-api": "0.1.0-alpha.0",
|
|
35
35
|
"@types/bun": "^1.3.8",
|
|
36
36
|
"@types/node": "22.19.2",
|