@tiwater/office-mcp 0.21.34 → 0.21.36
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/_shared/effect-kind.mjs +43 -0
- package/office/contracts/docx_read_table.schema.json +4 -11
- package/office/contracts/docx_replace_content_from_source.schema.json +4 -3
- package/office/contracts/docx_set_table.schema.json +107 -0
- package/office/contracts/tiwater-office-provider-contract-manifest-v1.json +10 -21
- package/office/index.mjs +105 -59
- package/package.json +1 -1
- package/pdf/contracts/tiwater-pdf-provider-contract-manifest-v1.json +1 -1
- package/text/contracts/tiwater-text-provider-contract-manifest-v1.json +1 -1
- package/office/contracts/docx_fill_table_from_tables.schema.json +0 -162
- package/office/contracts/docx_set_table_body.schema.json +0 -136
package/_shared/effect-kind.mjs
CHANGED
|
@@ -70,6 +70,17 @@ export function assertEffectKindToolContract(tool, expectedKind = undefined) {
|
|
|
70
70
|
return metadata.kind;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export function documentMutationFileArguments(tool, args) {
|
|
74
|
+
assertEffectKindToolContract(tool, 'document-mutation');
|
|
75
|
+
const bindings = boundFileArguments(tool?.inputSchema, args);
|
|
76
|
+
const current = bindings.filter(binding => binding.revisionRole === 'current');
|
|
77
|
+
const effectiveOutput = bindings.filter(binding => binding.role === 'write' && binding.effect);
|
|
78
|
+
if (current.length !== 1 || effectiveOutput.length !== 1) {
|
|
79
|
+
throw new Error(`document-mutation-file-arguments-invalid:${tool?.name || 'unnamed'}`);
|
|
80
|
+
}
|
|
81
|
+
return { current: current[0].value, effectiveOutput: effectiveOutput[0].value };
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
function fileBindings(schema) {
|
|
74
85
|
const bindings = [];
|
|
75
86
|
function visit(node) {
|
|
@@ -91,3 +102,35 @@ function fileBindings(schema) {
|
|
|
91
102
|
visit(schema);
|
|
92
103
|
return bindings;
|
|
93
104
|
}
|
|
105
|
+
|
|
106
|
+
function boundFileArguments(schema, value) {
|
|
107
|
+
const bindings = [];
|
|
108
|
+
function visit(node, currentValue) {
|
|
109
|
+
if (!node || typeof node !== 'object' || Array.isArray(node)) return;
|
|
110
|
+
if (node['x-tiwater-file-role'] === 'read' || node['x-tiwater-file-role'] === 'write') {
|
|
111
|
+
if (typeof currentValue !== 'string' || currentValue.length === 0) {
|
|
112
|
+
throw new Error('provider-file-argument-invalid');
|
|
113
|
+
}
|
|
114
|
+
bindings.push({
|
|
115
|
+
role: node['x-tiwater-file-role'],
|
|
116
|
+
effect: node['x-tiwater-file-role'] === 'write'
|
|
117
|
+
&& node['x-tiwater-file-effect'] !== false,
|
|
118
|
+
revisionRole: node[documentRevisionRoleKey],
|
|
119
|
+
value: currentValue,
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(currentValue)) {
|
|
124
|
+
for (const entry of currentValue) visit(node.items, entry);
|
|
125
|
+
} else if (currentValue && typeof currentValue === 'object') {
|
|
126
|
+
for (const [name, child] of Object.entries(node.properties || {})) {
|
|
127
|
+
if (Object.hasOwn(currentValue, name)) visit(child, currentValue[name]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for (const keyword of ['allOf', 'anyOf', 'oneOf']) {
|
|
131
|
+
for (const child of node[keyword] || []) visit(child, currentValue);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
visit(schema, value);
|
|
135
|
+
return bindings;
|
|
136
|
+
}
|
|
@@ -21,17 +21,10 @@
|
|
|
21
21
|
"required": ["part", "path"],
|
|
22
22
|
"additionalProperties": false
|
|
23
23
|
},
|
|
24
|
-
"
|
|
25
|
-
"type": "
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"description": "Maximum number of table rows requested in this response page. The provider may return fewer to keep the machine response bounded."
|
|
29
|
-
},
|
|
30
|
-
"offset": {
|
|
31
|
-
"type": "integer",
|
|
32
|
-
"minimum": 0,
|
|
33
|
-
"maximum": 9007199254740991,
|
|
34
|
-
"description": "Zero-based row offset. Continue only when an unreturned row is needed for the current operation; unused blank template rows need not be read."
|
|
24
|
+
"continuation": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"minLength": 1,
|
|
27
|
+
"description": "Opaque continuation returned by the preceding page. Pass it back unchanged; omit it for the first page."
|
|
35
28
|
},
|
|
36
29
|
"output": {
|
|
37
30
|
"type": "string",
|
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
"type": "string",
|
|
7
7
|
"minLength": 1,
|
|
8
8
|
"description": "Current target DOCX containing every target paragraph or table cell.",
|
|
9
|
-
"x-tiwater-file-role": "read",
|
|
9
|
+
"x-tiwater-file-role": "read",
|
|
10
|
+
"x-tiwater-document-revision-role": "current"
|
|
10
11
|
},
|
|
11
12
|
"changes": {
|
|
12
13
|
"minItems": 1,
|
|
13
14
|
"type": "array",
|
|
14
|
-
"description": "
|
|
15
|
+
"description": "Replace one or more existing target paragraphs or cells with explicit native source selections in one atomic commit. This preserves selected native runs but does not change rows, spans, or merges.",
|
|
15
16
|
"items": {
|
|
16
17
|
"type": "object",
|
|
17
18
|
"properties": {
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"sourceSelections": {
|
|
45
46
|
"minItems": 1,
|
|
46
47
|
"type": "array",
|
|
47
|
-
"description": "Ordered native source cells, paragraphs, runs, or text nodes.
|
|
48
|
+
"description": "Ordered native source cells, paragraphs, runs, or text nodes. The target becomes exactly these selections; omitted source content is omitted. When excluding parallel-language text, explicitly include every required language-neutral formula, number, unit, and symbol in source order. Consecutive selections from one source paragraph form one target paragraph; a range retains the native runs it crosses. A source paragraph boundary remains a target paragraph boundary. Selected content becomes the target content without Agent transcription.",
|
|
48
49
|
"items": {
|
|
49
50
|
"type": "object",
|
|
50
51
|
"properties": {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "tiwater.office-mcp-input/docx_set_table",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"input": { "type": "string", "minLength": 1, "x-tiwater-file-role": "read", "x-tiwater-document-revision-role": "current" },
|
|
7
|
+
"table": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"description": "Current target table address returned by docx_read_table or docx_table_index.",
|
|
10
|
+
"properties": {
|
|
11
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
12
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
13
|
+
},
|
|
14
|
+
"required": ["part", "path"], "additionalProperties": false
|
|
15
|
+
},
|
|
16
|
+
"existingRows": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"description": "Exact contiguous current row range to replace. Rows outside this range stay unchanged, and the range must enclose every vertical merge it intersects.",
|
|
19
|
+
"properties": {
|
|
20
|
+
"first": {
|
|
21
|
+
"type": "object", "properties": {
|
|
22
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
23
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
24
|
+
}, "required": ["part", "path"], "additionalProperties": false
|
|
25
|
+
},
|
|
26
|
+
"last": {
|
|
27
|
+
"type": "object", "properties": {
|
|
28
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
29
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
30
|
+
}, "required": ["part", "path"], "additionalProperties": false
|
|
31
|
+
}
|
|
32
|
+
}, "required": ["first", "last"], "additionalProperties": false
|
|
33
|
+
},
|
|
34
|
+
"columns": {
|
|
35
|
+
"type": "array", "minItems": 1,
|
|
36
|
+
"description": "Complete target table grid in native order. IDs are request-local names used only by rows below.",
|
|
37
|
+
"items": {
|
|
38
|
+
"type": "object", "properties": {
|
|
39
|
+
"id": { "type": "string", "minLength": 1, "maxLength": 80 },
|
|
40
|
+
"gridColumn": {
|
|
41
|
+
"type": "object", "properties": {
|
|
42
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
43
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
44
|
+
}, "required": ["part", "path"], "additionalProperties": false
|
|
45
|
+
}
|
|
46
|
+
}, "required": ["id", "gridColumn"], "additionalProperties": false
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"rows": {
|
|
50
|
+
"type": "array", "minItems": 0,
|
|
51
|
+
"description": "Final logical rows. Explicit cells plus active row spans cover the target grid exactly once.",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "object", "properties": {
|
|
54
|
+
"prototypeRow": {
|
|
55
|
+
"type": "object", "properties": {
|
|
56
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
57
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
58
|
+
}, "required": ["part", "path"], "additionalProperties": false
|
|
59
|
+
},
|
|
60
|
+
"cells": {
|
|
61
|
+
"type": "array", "minItems": 1,
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "object", "properties": {
|
|
64
|
+
"columns": { "type": "array", "minItems": 1, "description": "One or more contiguous request-local column IDs occupied by this cell.", "items": { "type": "string", "minLength": 1, "maxLength": 80 } },
|
|
65
|
+
"rowSpan": { "type": "integer", "minimum": 1, "maximum": 2147483647 },
|
|
66
|
+
"text": { "anyOf": [{ "type": "string" }, { "type": "null" }], "description": "Final derived plain text, or null when sourceContent is used." },
|
|
67
|
+
"sourceContent": {
|
|
68
|
+
"anyOf": [{
|
|
69
|
+
"type": "object",
|
|
70
|
+
"properties": {
|
|
71
|
+
"input": { "type": "string", "minLength": 1, "x-tiwater-file-role": "read" },
|
|
72
|
+
"selections": {
|
|
73
|
+
"type": "array", "minItems": 1,
|
|
74
|
+
"items": {
|
|
75
|
+
"type": "object", "properties": {
|
|
76
|
+
"address": {
|
|
77
|
+
"type": "object", "properties": {
|
|
78
|
+
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
79
|
+
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
80
|
+
}, "required": ["part", "path"], "additionalProperties": false
|
|
81
|
+
},
|
|
82
|
+
"range": {
|
|
83
|
+
"type": "object", "properties": {
|
|
84
|
+
"start": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 },
|
|
85
|
+
"length": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }
|
|
86
|
+
}, "required": ["start", "length"], "additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
}, "required": ["address"], "additionalProperties": false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, "required": ["input", "selections"], "additionalProperties": false
|
|
92
|
+
}, { "type": "null" }],
|
|
93
|
+
"description": "Exact ordered native source selections, or null when text is used."
|
|
94
|
+
}
|
|
95
|
+
}, "required": ["columns", "text", "sourceContent"], "additionalProperties": false
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"cantSplit": { "type": "boolean" }
|
|
99
|
+
}, "required": ["prototypeRow", "cells"], "additionalProperties": false
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"output": { "type": "string", "minLength": 1, "description": "Output DOCX path; may equal input for one atomic in-place update.", "x-tiwater-file-role": "write" },
|
|
103
|
+
"receiptOutput": { "type": "string", "minLength": 1, "x-tiwater-file-role": "write", "x-tiwater-file-effect": false }
|
|
104
|
+
},
|
|
105
|
+
"required": ["input", "table", "existingRows", "columns", "rows", "output", "receiptOutput"],
|
|
106
|
+
"additionalProperties": false
|
|
107
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema": "tiwater.office-provider-contract-manifest/v1",
|
|
3
3
|
"provider": {
|
|
4
4
|
"id": "@tiwater/office-mcp",
|
|
5
|
-
"version": "0.21.
|
|
5
|
+
"version": "0.21.36"
|
|
6
6
|
},
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
@@ -71,17 +71,6 @@
|
|
|
71
71
|
"sha256": "995eb1a5a8992e2a2186f2d7621b5eea7875eecd78ce153e77964d2942db2211"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
{
|
|
75
|
-
"name": "docx_fill_table_from_tables",
|
|
76
|
-
"providerContract": {
|
|
77
|
-
"source": "packages/docx-cli/contracts/mcp-input/docx_fill_table_from_tables.schema.json",
|
|
78
|
-
"sha256": "81d335ffaf20b896ae043e96a5a83f1beb3debbaf7404a99c8b4f06a62989c7d"
|
|
79
|
-
},
|
|
80
|
-
"inputContract": {
|
|
81
|
-
"path": "office/contracts/docx_fill_table_from_tables.schema.json",
|
|
82
|
-
"sha256": "81d335ffaf20b896ae043e96a5a83f1beb3debbaf7404a99c8b4f06a62989c7d"
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
74
|
{
|
|
86
75
|
"name": "docx_insert_objects",
|
|
87
76
|
"providerContract": {
|
|
@@ -152,11 +141,11 @@
|
|
|
152
141
|
"name": "docx_read_table",
|
|
153
142
|
"providerContract": {
|
|
154
143
|
"source": "packages/docx-cli/contracts/mcp-input/docx_read_table.schema.json",
|
|
155
|
-
"sha256": "
|
|
144
|
+
"sha256": "0b7a5669daeaa6f8e171ba01542b4bfd065cd282a32943e7b5b5854551b4afc7"
|
|
156
145
|
},
|
|
157
146
|
"inputContract": {
|
|
158
147
|
"path": "office/contracts/docx_read_table.schema.json",
|
|
159
|
-
"sha256": "
|
|
148
|
+
"sha256": "0b7a5669daeaa6f8e171ba01542b4bfd065cd282a32943e7b5b5854551b4afc7"
|
|
160
149
|
}
|
|
161
150
|
},
|
|
162
151
|
{
|
|
@@ -174,11 +163,11 @@
|
|
|
174
163
|
"name": "docx_replace_content_from_source",
|
|
175
164
|
"providerContract": {
|
|
176
165
|
"source": "packages/docx-cli/contracts/mcp-input/docx_replace_content_from_source.schema.json",
|
|
177
|
-
"sha256": "
|
|
166
|
+
"sha256": "04740981ad30190be4625ce3a2640b48abec02a9bc0eccc3e0e7d4fe40dbc6e0"
|
|
178
167
|
},
|
|
179
168
|
"inputContract": {
|
|
180
169
|
"path": "office/contracts/docx_replace_content_from_source.schema.json",
|
|
181
|
-
"sha256": "
|
|
170
|
+
"sha256": "04740981ad30190be4625ce3a2640b48abec02a9bc0eccc3e0e7d4fe40dbc6e0"
|
|
182
171
|
}
|
|
183
172
|
},
|
|
184
173
|
{
|
|
@@ -204,14 +193,14 @@
|
|
|
204
193
|
}
|
|
205
194
|
},
|
|
206
195
|
{
|
|
207
|
-
"name": "
|
|
196
|
+
"name": "docx_set_table",
|
|
208
197
|
"providerContract": {
|
|
209
|
-
"source": "packages/docx-cli/contracts/mcp-input/
|
|
210
|
-
"sha256": "
|
|
198
|
+
"source": "packages/docx-cli/contracts/mcp-input/docx_set_table.schema.json",
|
|
199
|
+
"sha256": "1b501654b6cd3ee58831393c9100ac37e1e5c21a5a92071a6f612b103aae122e"
|
|
211
200
|
},
|
|
212
201
|
"inputContract": {
|
|
213
|
-
"path": "office/contracts/
|
|
214
|
-
"sha256": "
|
|
202
|
+
"path": "office/contracts/docx_set_table.schema.json",
|
|
203
|
+
"sha256": "1b501654b6cd3ee58831393c9100ac37e1e5c21a5a92071a6f612b103aae122e"
|
|
215
204
|
}
|
|
216
205
|
},
|
|
217
206
|
{
|
package/office/index.mjs
CHANGED
|
@@ -24,7 +24,10 @@ import {
|
|
|
24
24
|
} from '../_shared/large-json-result.mjs';
|
|
25
25
|
import { withOutputWriteLock } from '../_shared/output-write-lock.mjs';
|
|
26
26
|
import { evidenceRoleMetadata } from '../_shared/evidence-role.mjs';
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
documentMutationFileArguments,
|
|
29
|
+
effectKindMetadata,
|
|
30
|
+
} from '../_shared/effect-kind.mjs';
|
|
28
31
|
import { compactDocxObjectIdentity } from './docx-object-identity.mjs';
|
|
29
32
|
|
|
30
33
|
const packageMetadata = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
@@ -38,14 +41,20 @@ if (inputContractManifest.provider?.id !== packageMetadata.name
|
|
|
38
41
|
}
|
|
39
42
|
const inputContracts = new Map(await Promise.all(inputContractManifest.tools.map(async entry => {
|
|
40
43
|
const schema = JSON.parse(await readFile(new URL(`./contracts/${entry.name}.schema.json`, import.meta.url), 'utf8'));
|
|
41
|
-
return [entry.name, z.fromJSONSchema(schema)];
|
|
44
|
+
return [entry.name, { schema, validator: z.fromJSONSchema(schema) }];
|
|
42
45
|
})));
|
|
43
46
|
const invocationCwd = process.cwd();
|
|
44
47
|
|
|
45
48
|
function inputContract(toolName) {
|
|
46
49
|
const contract = inputContracts.get(toolName);
|
|
47
50
|
if (!contract) throw new Error(`Missing provider-owned MCP input contract: ${toolName}`);
|
|
48
|
-
return contract;
|
|
51
|
+
return contract.validator;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function inputContractSchema(toolName) {
|
|
55
|
+
const contract = inputContracts.get(toolName);
|
|
56
|
+
if (!contract) throw new Error(`Missing provider-owned MCP input contract: ${toolName}`);
|
|
57
|
+
return contract.schema;
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
const docxCandidates = [
|
|
@@ -151,14 +160,14 @@ const xlsxFixedTools = [
|
|
|
151
160
|
{"name":"xlsx_set_column_width","description":"Set current worksheet column widths."},
|
|
152
161
|
];
|
|
153
162
|
|
|
154
|
-
function fixedToolDefinitions(definitions) {
|
|
163
|
+
function fixedToolDefinitions(definitions, candidates) {
|
|
155
164
|
return definitions.map(definition => ({
|
|
156
165
|
name: definition.name,
|
|
157
166
|
effectKind: 'document-mutation',
|
|
158
167
|
description: definition.description,
|
|
159
168
|
inputSchema: inputContract(definition.name),
|
|
160
169
|
outputSchema: fixedEditOutput(definition.name),
|
|
161
|
-
handler: args => fixedEdit(
|
|
170
|
+
handler: (args, tool) => fixedEdit(tool, args, candidates),
|
|
162
171
|
}));
|
|
163
172
|
}
|
|
164
173
|
|
|
@@ -372,9 +381,10 @@ const docxTableReadOutput = docxObservationOutput('docx_read_table').extend({
|
|
|
372
381
|
receipt: z.object({
|
|
373
382
|
schema: z.literal('tiwater.docx-table-page-receipt/v1'),
|
|
374
383
|
totalRowCount: z.number().int().nonnegative(),
|
|
384
|
+
retainedRowCount: z.number().int().nonnegative(),
|
|
375
385
|
returnedRowCount: z.number().int().nonnegative(),
|
|
376
386
|
remaining: z.number().int().nonnegative(),
|
|
377
|
-
|
|
387
|
+
nextContinuation: z.string().min(1).optional(),
|
|
378
388
|
detailPageRetained: z.boolean(),
|
|
379
389
|
narrowingRequired: z.boolean(),
|
|
380
390
|
}).strict(),
|
|
@@ -460,7 +470,7 @@ const tools = [
|
|
|
460
470
|
},
|
|
461
471
|
{
|
|
462
472
|
name: 'docx_read_table',
|
|
463
|
-
description: 'Read
|
|
473
|
+
description: 'Read one explicit native DOCX table. Provide output to retain every remaining row with full paragraph and text-node detail. Set returnContent true to also receive the largest compact inline page within the response limit; these channels are independent and at least one is required. retainedRowCount counts artifact rows and returnedRowCount counts inline rows. When remaining is nonzero, continue only by passing receipt.nextContinuation unchanged in the next call; a continuation page depends on the preceding receipt and cannot be predicted or read in parallel. Match columns by gridColumnStart, not tc position. A vertical-merge restart owns one logical value; a continue cell points to verticalMergeOwner and does not repeat that value inline.',
|
|
464
474
|
inputSchema: inputContract('docx_read_table'),
|
|
465
475
|
outputSchema: docxTableReadOutput,
|
|
466
476
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
@@ -469,10 +479,10 @@ const tools = [
|
|
|
469
479
|
{
|
|
470
480
|
name: 'docx_replace_content_from_source',
|
|
471
481
|
effectKind: 'document-mutation',
|
|
472
|
-
description: '
|
|
482
|
+
description: 'Atomically replace one or more existing target paragraphs or cells with exactly the selected native source content. Select source cells, paragraphs, runs, text nodes, or Unicode-scalar text ranges; omitted content is omitted, while selected runs retain superscript, subscript, formulas, numbers, units, and symbols. This tool does not change table rows, spans, or merges.',
|
|
473
483
|
inputSchema: inputContract('docx_replace_content_from_source'),
|
|
474
484
|
outputSchema: fixedEditOutput('docx_replace_content_from_source'),
|
|
475
|
-
handler: args => fixedEdit(
|
|
485
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
476
486
|
},
|
|
477
487
|
{
|
|
478
488
|
name: 'docx_set_text',
|
|
@@ -480,7 +490,7 @@ const tools = [
|
|
|
480
490
|
description: 'Replace the whole text content of paragraph or cell objects observed from this exact input DOCX while retaining target formatting, bookmarks, spans, and vertical merges. For a vertically merged logical cell, write its visible text to the restart cell rather than a continue cell. Tabs and line breaks remain native document text controls; targets containing non-text objects are rejected. Use this only for newly derived text. Content copied or selected from a source DOCX uses docx_replace_content_from_source so native runs such as superscript and subscript are retained. This does not insert objects, change table structure, copy source formatting, or decide business wording.',
|
|
481
491
|
inputSchema: inputContract('docx_set_text'),
|
|
482
492
|
outputSchema: fixedEditOutput('docx_set_text'),
|
|
483
|
-
handler: args => fixedEdit(
|
|
493
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
484
494
|
},
|
|
485
495
|
{
|
|
486
496
|
name: 'docx_set_paragraph_pagination',
|
|
@@ -488,23 +498,15 @@ const tools = [
|
|
|
488
498
|
description: 'Set native pagination properties on explicitly selected current DOCX paragraphs. Each change sets at least one pagination property. keepWithNext keeps a paragraph with the immediately following paragraph or table but does not guarantee that a table header remains with its first body row. keepLinesTogether keeps one paragraph on one page; pageBreakBefore starts it on a new page; preventWidowOrphanLines controls isolated first or last lines. Omitted properties remain unchanged. The caller chooses paragraphs from current native addresses; the provider does not decide document layout or business meaning.',
|
|
489
499
|
inputSchema: inputContract('docx_set_paragraph_pagination'),
|
|
490
500
|
outputSchema: fixedEditOutput('docx_set_paragraph_pagination'),
|
|
491
|
-
handler: args => fixedEdit(
|
|
501
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
492
502
|
},
|
|
493
503
|
{
|
|
494
|
-
name: '
|
|
504
|
+
name: 'docx_set_table',
|
|
495
505
|
effectKind: 'document-mutation',
|
|
496
|
-
description: 'Atomically replace one exact current target-table row range
|
|
497
|
-
inputSchema: inputContract('
|
|
498
|
-
outputSchema: fixedEditOutput('
|
|
499
|
-
handler: args => fixedEdit(
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
name: 'docx_fill_table_from_tables',
|
|
503
|
-
effectKind: 'document-mutation',
|
|
504
|
-
description: 'Fill one current target-table body from one or more explicitly ordered current source-table row ranges. For each source, select an unmerged record column when every physical source row must remain an output row; mapped columns still retain their native vertical merges. Select a merged record column only when every mapping into one target cell has one equal scalar value throughout that merge group. Map source grid columns onto every target prototype cell. The provider concatenates source records in declared order, copies each mapped source cell in full, preserves horizontal spans, rebuilds vertical merges only within each source range, validates the complete target grid, commits once, and returns structural readback. It does not discover source tables, choose source or target business meaning, filter records, translate or rewrite text, or apply business-specific rules. A single source uses the same sources array with one item. If a target needs only selected source descendants, such as one language from a bilingual cell, immediately use the returned target-cell addresses with docx_replace_content_from_source before releasing that source or reading back the completed target.',
|
|
505
|
-
inputSchema: inputContract('docx_fill_table_from_tables'),
|
|
506
|
-
outputSchema: fixedEditOutput('docx_fill_table_from_tables'),
|
|
507
|
-
handler: args => fixedEdit('docx_fill_table_from_tables', args),
|
|
506
|
+
description: 'Atomically replace one exact current target-table row range with a fully specified table body. Name every target grid column in native order. Each explicit cell occupies contiguous columns and may span logical rows; covered columns are omitted from following rows. Set each cell from either derived text or exact native source selections, never both. Native source selections retain run formatting such as superscript and subscript. The provider retains the target table, target cell styles, grid widths, and all content outside the replaced range, and exposes no intermediate document. It does not select source rows, map business columns, infer target shape, derive wording, or copy a source table wholesale.',
|
|
507
|
+
inputSchema: inputContract('docx_set_table'),
|
|
508
|
+
outputSchema: fixedEditOutput('docx_set_table'),
|
|
509
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
508
510
|
},
|
|
509
511
|
{
|
|
510
512
|
name: 'docx_insert_objects',
|
|
@@ -512,7 +514,7 @@ const tools = [
|
|
|
512
514
|
description: 'Insert selected current DOCX objects under an existing parent. Table rows are objects: expand a target table by copying one contiguous observed row range and use repeat for count; sourceInput may equal input. A row range beginning with vertical-merge continuations may be inserted only inside a target boundary with the same active grid spans, which extends those merges. Individual table cells are not raw insertion targets because that would bypass the table grid.',
|
|
513
515
|
inputSchema: inputContract('docx_insert_objects'),
|
|
514
516
|
outputSchema: fixedEditOutput('docx_insert_objects'),
|
|
515
|
-
handler: args => fixedEdit(
|
|
517
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
516
518
|
},
|
|
517
519
|
{
|
|
518
520
|
name: 'docx_delete_object',
|
|
@@ -520,7 +522,7 @@ const tools = [
|
|
|
520
522
|
description: 'Delete selected current DOCX objects directly from the current target document. Selected table rows must close every vertical merge and cannot remove the whole table. Individual table cells are not raw deletion targets; use column or merge operations for table structure.',
|
|
521
523
|
inputSchema: inputContract('docx_delete_object'),
|
|
522
524
|
outputSchema: fixedEditOutput('docx_delete_object'),
|
|
523
|
-
handler: args => fixedEdit(
|
|
525
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
524
526
|
},
|
|
525
527
|
{
|
|
526
528
|
name: 'docx_merge_cells',
|
|
@@ -528,7 +530,7 @@ const tools = [
|
|
|
528
530
|
description: 'Merge selected current DOCX cells when they form one closed rectangle. A one-column, multi-row rectangle creates a vertical merge whose first cell is the restart owner and whose later cells are continuations. All selected cell content moves into the top-left owner, so the selected content must already be correct for that one logical cell.',
|
|
529
531
|
inputSchema: inputContract('docx_merge_cells'),
|
|
530
532
|
outputSchema: fixedEditOutput('docx_merge_cells'),
|
|
531
|
-
handler: args => fixedEdit(
|
|
533
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
532
534
|
},
|
|
533
535
|
{
|
|
534
536
|
name: 'docx_split_cells',
|
|
@@ -536,7 +538,7 @@ const tools = [
|
|
|
536
538
|
description: 'Split selected current DOCX merged cells.',
|
|
537
539
|
inputSchema: inputContract('docx_split_cells'),
|
|
538
540
|
outputSchema: fixedEditOutput('docx_split_cells'),
|
|
539
|
-
handler: args => fixedEdit(
|
|
541
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
540
542
|
},
|
|
541
543
|
{
|
|
542
544
|
name: 'docx_insert_table_columns',
|
|
@@ -544,7 +546,7 @@ const tools = [
|
|
|
544
546
|
description: 'Insert empty template-shaped grid columns into one current main-document table. Select an observed source grid column for width and per-row cell formatting, and optionally a before grid-column address; cells spanning the insertion boundary expand instead of being split. It does not copy business values or decide column meaning.',
|
|
545
547
|
inputSchema: inputContract('docx_insert_table_columns'),
|
|
546
548
|
outputSchema: fixedEditOutput('docx_insert_table_columns'),
|
|
547
|
-
handler: args => fixedEdit(
|
|
549
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
548
550
|
},
|
|
549
551
|
{
|
|
550
552
|
name: 'docx_delete_table_columns',
|
|
@@ -552,7 +554,7 @@ const tools = [
|
|
|
552
554
|
description: 'Delete selected observed grid columns from one current main-document table while shrinking spanning cells and preserving the remaining table grid. It cannot remove every column and does not decide whether a business column is unused.',
|
|
553
555
|
inputSchema: inputContract('docx_delete_table_columns'),
|
|
554
556
|
outputSchema: fixedEditOutput('docx_delete_table_columns'),
|
|
555
|
-
handler: args => fixedEdit(
|
|
557
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
556
558
|
},
|
|
557
559
|
{
|
|
558
560
|
name: 'docx_compare',
|
|
@@ -593,7 +595,7 @@ const tools = [
|
|
|
593
595
|
description: 'Apply one explicit font family and size policy to current main-document body and table text. It does not derive a policy or alter other run semantics.',
|
|
594
596
|
inputSchema: inputContract('docx_apply_font_policy'),
|
|
595
597
|
outputSchema: fixedEditOutput('docx_apply_font_policy'),
|
|
596
|
-
handler: args => fixedEdit(
|
|
598
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
597
599
|
},
|
|
598
600
|
{
|
|
599
601
|
name: 'docx_validate_toc_style_policy',
|
|
@@ -609,7 +611,7 @@ const tools = [
|
|
|
609
611
|
description: 'Apply explicit italic and per-level indentation values to current built-in table-of-contents paragraph styles. It does not change heading text or refresh fields.',
|
|
610
612
|
inputSchema: inputContract('docx_apply_toc_style_policy'),
|
|
611
613
|
outputSchema: fixedEditOutput('docx_apply_toc_style_policy'),
|
|
612
|
-
handler: args => fixedEdit(
|
|
614
|
+
handler: (args, tool) => fixedEdit(tool, args, docxCandidates),
|
|
613
615
|
},
|
|
614
616
|
{
|
|
615
617
|
name: 'docx_refresh_fields',
|
|
@@ -676,7 +678,7 @@ const tools = [
|
|
|
676
678
|
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
677
679
|
handler: xlsxReadRange,
|
|
678
680
|
},
|
|
679
|
-
...fixedToolDefinitions(xlsxFixedTools),
|
|
681
|
+
...fixedToolDefinitions(xlsxFixedTools, xlsxCandidates),
|
|
680
682
|
{
|
|
681
683
|
name: 'xlsx_validate',
|
|
682
684
|
description: 'Validate an XLSX workbook package and produce OpenXML validation evidence. Set returnContent true to return the complete result when it fits the response limit. Provide output to write the complete result to a new JSON file. The two choices are independent and may be used together; at least one is required.',
|
|
@@ -709,7 +711,7 @@ const tools = [
|
|
|
709
711
|
description: 'Apply one deterministic PPTX template-application plan to a current presentation. This tool executes the published plan; it does not select a template or derive business content, slide mappings, geometry, or formatting decisions.',
|
|
710
712
|
inputSchema: inputContract('pptx_apply_template'),
|
|
711
713
|
outputSchema: fixedEditOutput('pptx_apply_template'),
|
|
712
|
-
handler: args => fixedEdit(
|
|
714
|
+
handler: (args, tool) => fixedEdit(tool, args, pptxCandidates),
|
|
713
715
|
},
|
|
714
716
|
{
|
|
715
717
|
name: 'pptx_apply_format',
|
|
@@ -717,7 +719,7 @@ const tools = [
|
|
|
717
719
|
description: 'Apply one deterministic PPTX formatting plan to a current presentation. This tool executes published formatting operations; it does not derive values, coordinates, or business decisions.',
|
|
718
720
|
inputSchema: inputContract('pptx_apply_format'),
|
|
719
721
|
outputSchema: fixedEditOutput('pptx_apply_format'),
|
|
720
|
-
handler: args => fixedEdit(
|
|
722
|
+
handler: (args, tool) => fixedEdit(tool, args, pptxCandidates),
|
|
721
723
|
},
|
|
722
724
|
{
|
|
723
725
|
name: 'pptx_set_shape_geometry',
|
|
@@ -725,7 +727,7 @@ const tools = [
|
|
|
725
727
|
description: 'Set exact native EMU bounds for uniquely identified current-slide PPTX objects. One call batches only this fixed geometry action and does not infer repair coordinates.',
|
|
726
728
|
inputSchema: inputContract('pptx_set_shape_geometry'),
|
|
727
729
|
outputSchema: fixedEditOutput('pptx_set_shape_geometry'),
|
|
728
|
-
handler: args => fixedEdit(
|
|
730
|
+
handler: (args, tool) => fixedEdit(tool, args, pptxCandidates),
|
|
729
731
|
},
|
|
730
732
|
{
|
|
731
733
|
name: 'pptx_replace_picture_image',
|
|
@@ -733,7 +735,7 @@ const tools = [
|
|
|
733
735
|
description: 'Replace embedded PNG or JPEG media for uniquely identified current-slide PPTX pictures while preserving the picture object, geometry, crop, and unrelated media. One call batches only this fixed replacement action.',
|
|
734
736
|
inputSchema: inputContract('pptx_replace_picture_image'),
|
|
735
737
|
outputSchema: fixedEditOutput('pptx_replace_picture_image'),
|
|
736
|
-
handler: args => fixedEdit(
|
|
738
|
+
handler: (args, tool) => fixedEdit(tool, args, pptxCandidates),
|
|
737
739
|
},
|
|
738
740
|
{
|
|
739
741
|
name: 'pptx_validate',
|
|
@@ -769,8 +771,8 @@ function buildServer() {
|
|
|
769
771
|
},
|
|
770
772
|
async args => {
|
|
771
773
|
const payload = typeof args.output === 'string'
|
|
772
|
-
? await withOutputWriteLock(args.output, () => tool.handler(args))
|
|
773
|
-
: await tool.handler(args);
|
|
774
|
+
? await withOutputWriteLock(args.output, () => tool.handler(args, tool))
|
|
775
|
+
: await tool.handler(args, tool);
|
|
774
776
|
return createToolResult(payload, { isError: payload?.summary?.pass === false });
|
|
775
777
|
},
|
|
776
778
|
);
|
|
@@ -853,6 +855,34 @@ async function docxInspect(args) {
|
|
|
853
855
|
};
|
|
854
856
|
}
|
|
855
857
|
|
|
858
|
+
function encodeTableContinuation(input, table, offset) {
|
|
859
|
+
return Buffer.from(JSON.stringify({
|
|
860
|
+
schema: 'tiwater.docx-table-continuation/v1',
|
|
861
|
+
input,
|
|
862
|
+
table,
|
|
863
|
+
offset,
|
|
864
|
+
})).toString('base64url');
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
function decodeTableContinuation(continuation, input, table) {
|
|
868
|
+
if (continuation === undefined) return 0;
|
|
869
|
+
let decoded;
|
|
870
|
+
try {
|
|
871
|
+
decoded = JSON.parse(Buffer.from(continuation, 'base64url').toString('utf8'));
|
|
872
|
+
} catch {
|
|
873
|
+
throw new Error('invalid-docx-table-continuation');
|
|
874
|
+
}
|
|
875
|
+
if (decoded?.schema !== 'tiwater.docx-table-continuation/v1'
|
|
876
|
+
|| decoded.input !== input
|
|
877
|
+
|| decoded.table?.part !== table?.part
|
|
878
|
+
|| decoded.table?.path !== table?.path
|
|
879
|
+
|| !Number.isSafeInteger(decoded.offset)
|
|
880
|
+
|| decoded.offset < 0) {
|
|
881
|
+
throw new Error('invalid-docx-table-continuation');
|
|
882
|
+
}
|
|
883
|
+
return decoded.offset;
|
|
884
|
+
}
|
|
885
|
+
|
|
856
886
|
async function docxObservation(tool, args) {
|
|
857
887
|
const input = path.resolve(requireString(args.input, 'input'));
|
|
858
888
|
const delivery = resultChannels(args);
|
|
@@ -947,18 +977,20 @@ async function docxObservation(tool, args) {
|
|
|
947
977
|
}
|
|
948
978
|
if (tool === 'docx_read_table') {
|
|
949
979
|
const totalRowCount = payload.rows.length;
|
|
950
|
-
const offset = Math.min(args.
|
|
951
|
-
const
|
|
952
|
-
const selectedRows = payload.rows.slice(offset, offset + requestedLimit);
|
|
980
|
+
const offset = Math.min(decodeTableContinuation(args.continuation, input, args.table), totalRowCount);
|
|
981
|
+
const selectedRows = payload.rows.slice(offset);
|
|
953
982
|
const selectedNextOffset = offset + selectedRows.length < totalRowCount
|
|
954
983
|
? offset + selectedRows.length
|
|
955
984
|
: null;
|
|
956
985
|
const selectedPageReceipt = {
|
|
957
986
|
schema: 'tiwater.docx-table-page-receipt/v1',
|
|
958
987
|
totalRowCount,
|
|
988
|
+
retainedRowCount: selectedRows.length,
|
|
959
989
|
returnedRowCount: selectedRows.length,
|
|
960
990
|
remaining: totalRowCount - offset - selectedRows.length,
|
|
961
|
-
...(selectedNextOffset === null ? {} : {
|
|
991
|
+
...(selectedNextOffset === null ? {} : {
|
|
992
|
+
nextContinuation: encodeTableContinuation(input, args.table, selectedNextOffset),
|
|
993
|
+
}),
|
|
962
994
|
};
|
|
963
995
|
const detailPage = {
|
|
964
996
|
schema: 'tiwater.docx-table-detail-page/v1',
|
|
@@ -987,6 +1019,7 @@ async function docxObservation(tool, args) {
|
|
|
987
1019
|
followingParagraph: payload.followingParagraph,
|
|
988
1020
|
receipt: {
|
|
989
1021
|
...selectedPageReceipt,
|
|
1022
|
+
returnedRowCount: 0,
|
|
990
1023
|
detailPageRetained: true,
|
|
991
1024
|
narrowingRequired: false,
|
|
992
1025
|
},
|
|
@@ -1008,7 +1041,7 @@ async function docxObservation(tool, args) {
|
|
|
1008
1041
|
verticalMerge: cell.verticalMerge,
|
|
1009
1042
|
verticalMergeOwner: cell.verticalMergeOwner,
|
|
1010
1043
|
text: cell.paragraphs.map(paragraph => paragraph.text).join('\n'),
|
|
1011
|
-
logicalText: cell.logicalText,
|
|
1044
|
+
logicalText: cell.verticalMerge === 'continue' ? '' : cell.logicalText,
|
|
1012
1045
|
})),
|
|
1013
1046
|
};
|
|
1014
1047
|
const candidate = [...rows, row];
|
|
@@ -1018,15 +1051,19 @@ async function docxObservation(tool, args) {
|
|
|
1018
1051
|
}
|
|
1019
1052
|
rows.push(row);
|
|
1020
1053
|
}
|
|
1021
|
-
const
|
|
1054
|
+
const retainedRowCount = delivery.output === null ? rows.length : selectedRows.length;
|
|
1055
|
+
const inlineNextOffset = offset + rows.length < totalRowCount
|
|
1022
1056
|
? offset + rows.length
|
|
1023
1057
|
: null;
|
|
1024
1058
|
const pageReceipt = {
|
|
1025
1059
|
schema: 'tiwater.docx-table-page-receipt/v1',
|
|
1026
1060
|
totalRowCount,
|
|
1061
|
+
retainedRowCount,
|
|
1027
1062
|
returnedRowCount: rows.length,
|
|
1028
1063
|
remaining: totalRowCount - offset - rows.length,
|
|
1029
|
-
...(
|
|
1064
|
+
...(inlineNextOffset === null ? {} : {
|
|
1065
|
+
nextContinuation: encodeTableContinuation(input, args.table, inlineNextOffset),
|
|
1066
|
+
}),
|
|
1030
1067
|
};
|
|
1031
1068
|
return {
|
|
1032
1069
|
...withArtifact,
|
|
@@ -1040,7 +1077,7 @@ async function docxObservation(tool, args) {
|
|
|
1040
1077
|
receipt: {
|
|
1041
1078
|
...pageReceipt,
|
|
1042
1079
|
detailPageRetained: delivery.output !== null,
|
|
1043
|
-
narrowingRequired,
|
|
1080
|
+
narrowingRequired: delivery.output === null && narrowingRequired,
|
|
1044
1081
|
},
|
|
1045
1082
|
rows,
|
|
1046
1083
|
};
|
|
@@ -1165,28 +1202,37 @@ async function copyTransform(tool, candidates, command, args, suffix = []) {
|
|
|
1165
1202
|
}
|
|
1166
1203
|
}
|
|
1167
1204
|
|
|
1168
|
-
async function fixedEdit(tool, args) {
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1205
|
+
async function fixedEdit(tool, args, candidates) {
|
|
1206
|
+
const publishedContract = {
|
|
1207
|
+
name: tool.name,
|
|
1208
|
+
inputSchema: inputContractSchema(tool.name),
|
|
1209
|
+
annotations: tool.annotations,
|
|
1210
|
+
_meta: effectKindMetadata(tool.effectKind),
|
|
1211
|
+
};
|
|
1212
|
+
const bindings = documentMutationFileArguments(publishedContract, args);
|
|
1213
|
+
const input = path.resolve(bindings.current);
|
|
1214
|
+
const output = path.resolve(bindings.effectiveOutput);
|
|
1171
1215
|
const receiptOutput = path.resolve(requireString(args.receiptOutput, 'receiptOutput'));
|
|
1172
|
-
if (
|
|
1216
|
+
if (input !== output) await requireNewFile(output, 'output');
|
|
1173
1217
|
await requireNewFile(receiptOutput, 'receiptOutput');
|
|
1174
|
-
const candidates = tool.startsWith('docx_') ? docxCandidates
|
|
1175
|
-
: tool.startsWith('xlsx_') ? xlsxCandidates
|
|
1176
|
-
: pptxCandidates;
|
|
1177
1218
|
return withTempJsonFile(args, async requestPath => {
|
|
1178
|
-
const result = await runJsonCandidateChain(candidates, [tool, requestPath], { allowedExitCodes: [0, 1] });
|
|
1219
|
+
const result = await runJsonCandidateChain(candidates, [tool.name, requestPath], { allowedExitCodes: [0, 1] });
|
|
1179
1220
|
if (result.code !== 0) {
|
|
1180
|
-
const detail = result.stderr.trim() || result.stdout.trim()
|
|
1221
|
+
const detail = result.stderr.trim() || result.stdout.trim()
|
|
1222
|
+
|| `${tool.name} failed with exit code ${result.code}`;
|
|
1181
1223
|
throw new Error(detail);
|
|
1182
1224
|
}
|
|
1183
|
-
if (result.json?.tool !== tool) throw new Error(`${tool} returned a mismatched tool identity`);
|
|
1225
|
+
if (result.json?.tool !== tool.name) throw new Error(`${tool.name} returned a mismatched tool identity`);
|
|
1184
1226
|
await requireReturnedArtifact(result.json.receipt, receiptOutput, 'receipt');
|
|
1185
1227
|
if (result.json.output === null) {
|
|
1186
|
-
if (result.json.summary?.pass !== false)
|
|
1228
|
+
if (result.json.summary?.pass !== false) {
|
|
1229
|
+
throw new Error(`${tool.name} omitted output without reporting failure`);
|
|
1230
|
+
}
|
|
1187
1231
|
} else {
|
|
1188
1232
|
await requireReturnedArtifact(result.json.output, output, 'output');
|
|
1189
|
-
if (result.json.summary?.pass !== true)
|
|
1233
|
+
if (result.json.summary?.pass !== true) {
|
|
1234
|
+
throw new Error(`${tool.name} returned output without reporting success`);
|
|
1235
|
+
}
|
|
1190
1236
|
}
|
|
1191
1237
|
return { ...result.json, runtime: commandRuntime(result) };
|
|
1192
1238
|
});
|
package/package.json
CHANGED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "tiwater.office-mcp-input/docx_fill_table_from_tables",
|
|
4
|
-
"description": "Project source-table rows into one target template table atomically. Use this instead of manually rebuilding rows when target cells derive from source tables. Target formatting is reused, and native vertical-merge owners are preserved within each source range.",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"input": { "type": "string", "minLength": 1, "description": "Current target DOCX.", "x-tiwater-file-role": "read", "x-tiwater-document-revision-role": "current" },
|
|
8
|
-
"table": {
|
|
9
|
-
"type": "object",
|
|
10
|
-
"description": "Current target table address returned by docx_read_table or docx_table_index.",
|
|
11
|
-
"properties": {
|
|
12
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
13
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
14
|
-
},
|
|
15
|
-
"required": ["part", "path"],
|
|
16
|
-
"additionalProperties": false
|
|
17
|
-
},
|
|
18
|
-
"existingRows": {
|
|
19
|
-
"type": "object",
|
|
20
|
-
"description": "Exact contiguous current target row range to replace; it must enclose every vertical merge it intersects.",
|
|
21
|
-
"properties": {
|
|
22
|
-
"first": {
|
|
23
|
-
"type": "object",
|
|
24
|
-
"properties": {
|
|
25
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
26
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
27
|
-
},
|
|
28
|
-
"required": ["part", "path"],
|
|
29
|
-
"additionalProperties": false
|
|
30
|
-
},
|
|
31
|
-
"last": {
|
|
32
|
-
"type": "object",
|
|
33
|
-
"properties": {
|
|
34
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
35
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
36
|
-
},
|
|
37
|
-
"required": ["part", "path"],
|
|
38
|
-
"additionalProperties": false
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
"required": ["first", "last"],
|
|
42
|
-
"additionalProperties": false
|
|
43
|
-
},
|
|
44
|
-
"prototypeRow": {
|
|
45
|
-
"type": "object",
|
|
46
|
-
"description": "One current row inside existingRows whose cell formatting is reused for every generated body row.",
|
|
47
|
-
"properties": {
|
|
48
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
49
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
50
|
-
},
|
|
51
|
-
"required": ["part", "path"],
|
|
52
|
-
"additionalProperties": false
|
|
53
|
-
},
|
|
54
|
-
"sources": {
|
|
55
|
-
"type": "array",
|
|
56
|
-
"minItems": 1,
|
|
57
|
-
"description": "Ordered source-table ranges whose logical records are concatenated into the target body. Source boundaries never create a vertical merge with one another.",
|
|
58
|
-
"items": {
|
|
59
|
-
"type": "object",
|
|
60
|
-
"properties": {
|
|
61
|
-
"input": { "type": "string", "minLength": 1, "description": "Current source DOCX.", "x-tiwater-file-role": "read" },
|
|
62
|
-
"table": {
|
|
63
|
-
"type": "object",
|
|
64
|
-
"description": "Current source table address.",
|
|
65
|
-
"properties": {
|
|
66
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
67
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
68
|
-
},
|
|
69
|
-
"required": ["part", "path"],
|
|
70
|
-
"additionalProperties": false
|
|
71
|
-
},
|
|
72
|
-
"rows": {
|
|
73
|
-
"type": "object",
|
|
74
|
-
"description": "Exact contiguous source data-row range. Intersecting native vertical merges are clipped to this range, retain their owner content, and restart at the first selected row.",
|
|
75
|
-
"properties": {
|
|
76
|
-
"first": {
|
|
77
|
-
"type": "object",
|
|
78
|
-
"properties": {
|
|
79
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
80
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
81
|
-
},
|
|
82
|
-
"required": ["part", "path"],
|
|
83
|
-
"additionalProperties": false
|
|
84
|
-
},
|
|
85
|
-
"last": {
|
|
86
|
-
"type": "object",
|
|
87
|
-
"properties": {
|
|
88
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
89
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
90
|
-
},
|
|
91
|
-
"required": ["part", "path"],
|
|
92
|
-
"additionalProperties": false
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
"required": ["first", "last"],
|
|
96
|
-
"additionalProperties": false
|
|
97
|
-
},
|
|
98
|
-
"recordColumn": {
|
|
99
|
-
"type": "object",
|
|
100
|
-
"description": "Source grid-column address that defines output-row records. Choose an unmerged column when every physical source row must remain an output row; vertical merges in other mapped columns are still preserved. Choose a merged column only when every mapping into one target cell has one equal scalar value throughout that merge group.",
|
|
101
|
-
"properties": {
|
|
102
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
103
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
104
|
-
},
|
|
105
|
-
"required": ["part", "path"],
|
|
106
|
-
"additionalProperties": false
|
|
107
|
-
},
|
|
108
|
-
"columnMappings": {
|
|
109
|
-
"type": "array",
|
|
110
|
-
"minItems": 1,
|
|
111
|
-
"description": "Complete projection from this source grid onto all target prototype cells. Multiple adjacent source columns may compose one target cell; one source column may spread its logical values across several target cells.",
|
|
112
|
-
"items": {
|
|
113
|
-
"type": "object",
|
|
114
|
-
"properties": {
|
|
115
|
-
"sourceColumns": {
|
|
116
|
-
"type": "array",
|
|
117
|
-
"minItems": 1,
|
|
118
|
-
"description": "One or more contiguous source grid columns in native order. Multiple columns compose one target cell; a source cell spanning several selected columns contributes once.",
|
|
119
|
-
"items": {
|
|
120
|
-
"type": "object",
|
|
121
|
-
"properties": {
|
|
122
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
123
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
124
|
-
},
|
|
125
|
-
"required": ["part", "path"],
|
|
126
|
-
"additionalProperties": false
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
"targetColumns": {
|
|
130
|
-
"type": "array",
|
|
131
|
-
"minItems": 1,
|
|
132
|
-
"description": "One or more contiguous target grid columns covering complete prototype cells.",
|
|
133
|
-
"items": {
|
|
134
|
-
"type": "object",
|
|
135
|
-
"properties": {
|
|
136
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
137
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
138
|
-
},
|
|
139
|
-
"required": ["part", "path"],
|
|
140
|
-
"additionalProperties": false
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
"joinWith": {
|
|
144
|
-
"type": "string",
|
|
145
|
-
"description": "Separator used when sourceColumns compose one target cell. Defaults to a newline."
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
"required": ["sourceColumns", "targetColumns"],
|
|
149
|
-
"additionalProperties": false
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
"required": ["input", "table", "rows", "recordColumn", "columnMappings"],
|
|
154
|
-
"additionalProperties": false
|
|
155
|
-
}
|
|
156
|
-
},
|
|
157
|
-
"output": { "type": "string", "minLength": 1, "description": "Output DOCX path; may equal input for one atomic in-place update.", "x-tiwater-file-role": "write" },
|
|
158
|
-
"receiptOutput": { "type": "string", "minLength": 1, "x-tiwater-file-role": "write", "x-tiwater-file-effect": false }
|
|
159
|
-
},
|
|
160
|
-
"required": ["input", "table", "existingRows", "prototypeRow", "sources", "output", "receiptOutput"],
|
|
161
|
-
"additionalProperties": false
|
|
162
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "tiwater.office-mcp-input/docx_set_table_body",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"properties": {
|
|
6
|
-
"input": {
|
|
7
|
-
"type": "string",
|
|
8
|
-
"minLength": 1,
|
|
9
|
-
"x-tiwater-file-role": "read", "x-tiwater-document-revision-role": "current"
|
|
10
|
-
},
|
|
11
|
-
"table": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"properties": {
|
|
14
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
15
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
16
|
-
},
|
|
17
|
-
"required": ["part", "path"],
|
|
18
|
-
"additionalProperties": false,
|
|
19
|
-
"description": "Current target table address returned by docx_read_table or docx_table_index."
|
|
20
|
-
},
|
|
21
|
-
"existingRows": {
|
|
22
|
-
"type": "object",
|
|
23
|
-
"description": "Exact contiguous current row range to replace. Rows outside this range stay unchanged, and the range must enclose every vertical merge it intersects.",
|
|
24
|
-
"properties": {
|
|
25
|
-
"first": {
|
|
26
|
-
"type": "object",
|
|
27
|
-
"properties": {
|
|
28
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
29
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
30
|
-
},
|
|
31
|
-
"required": ["part", "path"],
|
|
32
|
-
"additionalProperties": false
|
|
33
|
-
},
|
|
34
|
-
"last": {
|
|
35
|
-
"type": "object",
|
|
36
|
-
"properties": {
|
|
37
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
38
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
39
|
-
},
|
|
40
|
-
"required": ["part", "path"],
|
|
41
|
-
"additionalProperties": false
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
"required": ["first", "last"],
|
|
45
|
-
"additionalProperties": false
|
|
46
|
-
},
|
|
47
|
-
"columns": {
|
|
48
|
-
"type": "array",
|
|
49
|
-
"minItems": 1,
|
|
50
|
-
"description": "Complete target table grid in the native order returned by docx_read_table. IDs are request-local names used only by rows below.",
|
|
51
|
-
"items": {
|
|
52
|
-
"type": "object",
|
|
53
|
-
"properties": {
|
|
54
|
-
"id": { "type": "string", "minLength": 1, "maxLength": 80 },
|
|
55
|
-
"gridColumn": {
|
|
56
|
-
"type": "object",
|
|
57
|
-
"properties": {
|
|
58
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
59
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
60
|
-
},
|
|
61
|
-
"required": ["part", "path"],
|
|
62
|
-
"additionalProperties": false
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
"required": ["id", "gridColumn"],
|
|
66
|
-
"additionalProperties": false
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
"rows": {
|
|
70
|
-
"type": "array",
|
|
71
|
-
"minItems": 0,
|
|
72
|
-
"description": "Final logical rows; an empty array removes the range when another row remains. Cells plus active row spans cover the complete target grid exactly once.",
|
|
73
|
-
"items": {
|
|
74
|
-
"type": "object",
|
|
75
|
-
"properties": {
|
|
76
|
-
"prototypeRow": {
|
|
77
|
-
"type": "object",
|
|
78
|
-
"properties": {
|
|
79
|
-
"part": { "type": "string", "minLength": 1, "pattern": "^\\/" },
|
|
80
|
-
"path": { "type": "string", "pattern": "^\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\](?:\\/[A-Za-z_][A-Za-z0-9_.-]*:[A-Za-z_][A-Za-z0-9_.-]*\\[[1-9][0-9]*\\])*$" }
|
|
81
|
-
},
|
|
82
|
-
"required": ["part", "path"],
|
|
83
|
-
"additionalProperties": false
|
|
84
|
-
},
|
|
85
|
-
"cells": {
|
|
86
|
-
"type": "array",
|
|
87
|
-
"minItems": 1,
|
|
88
|
-
"items": {
|
|
89
|
-
"type": "object",
|
|
90
|
-
"properties": {
|
|
91
|
-
"columns": {
|
|
92
|
-
"type": "array",
|
|
93
|
-
"minItems": 1,
|
|
94
|
-
"description": "One or more contiguous request-local column IDs occupied by this cell.",
|
|
95
|
-
"items": { "type": "string", "minLength": 1, "maxLength": 80 }
|
|
96
|
-
},
|
|
97
|
-
"text": {
|
|
98
|
-
"type": "string",
|
|
99
|
-
"description": "Final plain text for this cell. If the current cell at the same row and grid span already has exactly this text, its native paragraphs and run formatting are retained while row and merge properties are updated."
|
|
100
|
-
},
|
|
101
|
-
"rowSpan": {
|
|
102
|
-
"type": "integer",
|
|
103
|
-
"minimum": 1,
|
|
104
|
-
"maximum": 2147483647,
|
|
105
|
-
"description": "Logical row count occupied by this cell; omitted means one. Later rows omit these columns."
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
"required": ["columns", "text"],
|
|
109
|
-
"additionalProperties": false
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
"cantSplit": {
|
|
113
|
-
"type": "boolean",
|
|
114
|
-
"description": "Whether Word may split this physical row across pages. Omit to preserve the prototype row property."
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
"required": ["prototypeRow", "cells"],
|
|
118
|
-
"additionalProperties": false
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
"output": {
|
|
122
|
-
"type": "string",
|
|
123
|
-
"minLength": 1,
|
|
124
|
-
"description": "Output DOCX path; may equal input for one atomic in-place update.",
|
|
125
|
-
"x-tiwater-file-role": "write"
|
|
126
|
-
},
|
|
127
|
-
"receiptOutput": {
|
|
128
|
-
"type": "string",
|
|
129
|
-
"minLength": 1,
|
|
130
|
-
"x-tiwater-file-role": "write",
|
|
131
|
-
"x-tiwater-file-effect": false
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
"required": ["input", "table", "existingRows", "columns", "rows", "output", "receiptOutput"],
|
|
135
|
-
"additionalProperties": false
|
|
136
|
-
}
|