@documonster/mcp 0.8.0-canary.sha.09791dab

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +205 -0
  2. package/README.md +253 -0
  3. package/dist/capabilities.d.ts +29 -0
  4. package/dist/capabilities.d.ts.map +1 -0
  5. package/dist/capabilities.js +188 -0
  6. package/dist/capabilities.js.map +1 -0
  7. package/dist/cli.d.ts +13 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +64 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +65 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +189 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/errors.d.ts +66 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +96 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +25 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +20 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/sandbox.d.ts +86 -0
  24. package/dist/sandbox.d.ts.map +1 -0
  25. package/dist/sandbox.js +224 -0
  26. package/dist/sandbox.js.map +1 -0
  27. package/dist/server.d.ts +22 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +66 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/tools/archive-read.d.ts +31 -0
  32. package/dist/tools/archive-read.d.ts.map +1 -0
  33. package/dist/tools/archive-read.js +315 -0
  34. package/dist/tools/archive-read.js.map +1 -0
  35. package/dist/tools/archive-write.d.ts +9 -0
  36. package/dist/tools/archive-write.d.ts.map +1 -0
  37. package/dist/tools/archive-write.js +219 -0
  38. package/dist/tools/archive-write.js.map +1 -0
  39. package/dist/tools/chart.d.ts +93 -0
  40. package/dist/tools/chart.d.ts.map +1 -0
  41. package/dist/tools/chart.js +263 -0
  42. package/dist/tools/chart.js.map +1 -0
  43. package/dist/tools/doc-convert.d.ts +13 -0
  44. package/dist/tools/doc-convert.d.ts.map +1 -0
  45. package/dist/tools/doc-convert.js +209 -0
  46. package/dist/tools/doc-convert.js.map +1 -0
  47. package/dist/tools/doc-paginate.d.ts +14 -0
  48. package/dist/tools/doc-paginate.d.ts.map +1 -0
  49. package/dist/tools/doc-paginate.js +153 -0
  50. package/dist/tools/doc-paginate.js.map +1 -0
  51. package/dist/tools/doc-read.d.ts +14 -0
  52. package/dist/tools/doc-read.d.ts.map +1 -0
  53. package/dist/tools/doc-read.js +175 -0
  54. package/dist/tools/doc-read.js.map +1 -0
  55. package/dist/tools/doc-review.d.ts +17 -0
  56. package/dist/tools/doc-review.d.ts.map +1 -0
  57. package/dist/tools/doc-review.js +249 -0
  58. package/dist/tools/doc-review.js.map +1 -0
  59. package/dist/tools/doc-search.d.ts +20 -0
  60. package/dist/tools/doc-search.d.ts.map +1 -0
  61. package/dist/tools/doc-search.js +268 -0
  62. package/dist/tools/doc-search.js.map +1 -0
  63. package/dist/tools/doc-write.d.ts +11 -0
  64. package/dist/tools/doc-write.d.ts.map +1 -0
  65. package/dist/tools/doc-write.js +81 -0
  66. package/dist/tools/doc-write.js.map +1 -0
  67. package/dist/tools/document.d.ts +74 -0
  68. package/dist/tools/document.d.ts.map +1 -0
  69. package/dist/tools/document.js +157 -0
  70. package/dist/tools/document.js.map +1 -0
  71. package/dist/tools/form-fill.d.ts +20 -0
  72. package/dist/tools/form-fill.d.ts.map +1 -0
  73. package/dist/tools/form-fill.js +270 -0
  74. package/dist/tools/form-fill.js.map +1 -0
  75. package/dist/tools/formula-evaluate.d.ts +14 -0
  76. package/dist/tools/formula-evaluate.d.ts.map +1 -0
  77. package/dist/tools/formula-evaluate.js +192 -0
  78. package/dist/tools/formula-evaluate.js.map +1 -0
  79. package/dist/tools/fs-helpers.d.ts +106 -0
  80. package/dist/tools/fs-helpers.d.ts.map +1 -0
  81. package/dist/tools/fs-helpers.js +257 -0
  82. package/dist/tools/fs-helpers.js.map +1 -0
  83. package/dist/tools/help.d.ts +227 -0
  84. package/dist/tools/help.d.ts.map +1 -0
  85. package/dist/tools/help.js +262 -0
  86. package/dist/tools/help.js.map +1 -0
  87. package/dist/tools/index.d.ts +33 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +78 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/inspect.d.ts +14 -0
  92. package/dist/tools/inspect.d.ts.map +1 -0
  93. package/dist/tools/inspect.js +463 -0
  94. package/dist/tools/inspect.js.map +1 -0
  95. package/dist/tools/pdf-edit.d.ts +26 -0
  96. package/dist/tools/pdf-edit.d.ts.map +1 -0
  97. package/dist/tools/pdf-edit.js +390 -0
  98. package/dist/tools/pdf-edit.js.map +1 -0
  99. package/dist/tools/result.d.ts +25 -0
  100. package/dist/tools/result.d.ts.map +1 -0
  101. package/dist/tools/result.js +43 -0
  102. package/dist/tools/result.js.map +1 -0
  103. package/dist/tools/sheet-edit.d.ts +16 -0
  104. package/dist/tools/sheet-edit.d.ts.map +1 -0
  105. package/dist/tools/sheet-edit.js +325 -0
  106. package/dist/tools/sheet-edit.js.map +1 -0
  107. package/dist/tools/sheet-read.d.ts +10 -0
  108. package/dist/tools/sheet-read.d.ts.map +1 -0
  109. package/dist/tools/sheet-read.js +139 -0
  110. package/dist/tools/sheet-read.js.map +1 -0
  111. package/dist/tools/sheet-write.d.ts +15 -0
  112. package/dist/tools/sheet-write.d.ts.map +1 -0
  113. package/dist/tools/sheet-write.js +290 -0
  114. package/dist/tools/sheet-write.js.map +1 -0
  115. package/dist/tools/spreadsheet.d.ts +100 -0
  116. package/dist/tools/spreadsheet.d.ts.map +1 -0
  117. package/dist/tools/spreadsheet.js +210 -0
  118. package/dist/tools/spreadsheet.js.map +1 -0
  119. package/dist/tools/template.d.ts +18 -0
  120. package/dist/tools/template.d.ts.map +1 -0
  121. package/dist/tools/template.js +209 -0
  122. package/dist/tools/template.js.map +1 -0
  123. package/dist/tools/types.d.ts +79 -0
  124. package/dist/tools/types.d.ts.map +1 -0
  125. package/dist/tools/types.js +18 -0
  126. package/dist/tools/types.js.map +1 -0
  127. package/package.json +74 -0
@@ -0,0 +1,315 @@
1
+ /**
2
+ * `archive_read` — list or extract a ZIP/TAR archive.
3
+ *
4
+ * The entry point to most real work: documents arrive as email attachments and
5
+ * export bundles, and a model cannot open a binary container by itself. It is
6
+ * also where the security surface is widest, so three guards apply beyond the
7
+ * generic path sandbox:
8
+ *
9
+ * 1. **Traversal, including through existing links.** Entries are written one at
10
+ * a time and every destination goes through `resolveInRoot`, so an entry name
11
+ * with `..` is rejected *and* so is an entry whose path passes through a
12
+ * symlink already sitting in the destination directory. Delegating to the
13
+ * library's `extractTo` was not enough: it validates entry names against the
14
+ * target directory but writes through a pre-existing `out/link -> /elsewhere`,
15
+ * which was verified to escape the sandbox.
16
+ * 2. **Decompression bombs** — the archive file's own size is checked before it
17
+ * is opened, and the declared uncompressed sizes before anything is written.
18
+ * 3. **Symlink and special entries** — never materialised. A `link ->
19
+ * /etc/passwd` entry would otherwise leave a live escape hatch inside the
20
+ * sandbox for a later tool to follow.
21
+ * 4. **Permissions** — extracted files get the process default rather than the
22
+ * archive's mode bits, so an untrusted archive cannot produce something
23
+ * executable or world-writable.
24
+ *
25
+ * Encryption is not reported when listing: `ArchiveEntryInfo` carries an
26
+ * `isEncrypted` flag at runtime but does not declare it, and this package reads
27
+ * only documented public surface. Encryption therefore surfaces as a failed
28
+ * extraction with a hint to pass `password`. (Worth declaring upstream.)
29
+ */
30
+ import { copyFile, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
31
+ import path from "node:path";
32
+ import { Archive, ArchiveFile } from "documonster/archive";
33
+ import { z } from "zod";
34
+ import { McpToolError, toolError } from "../errors.js";
35
+ import { assertWritable, resolveInRoot, resolveOutputPath } from "../sandbox.js";
36
+ import { ensureParent, exists, writeWithPolicy } from "./fs-helpers.js";
37
+ import { formatBytes, textResult } from "./result.js";
38
+ import { defineTool } from "./types.js";
39
+ /** Entries listed in one call. */
40
+ const MAX_LISTED = 300;
41
+ /** Total uncompressed bytes allowed in one extraction (256 MiB). */
42
+ const MAX_TOTAL_EXTRACTED = 256 * 1024 * 1024;
43
+ /** Entry count allowed in one extraction. */
44
+ const MAX_ENTRIES = 5_000;
45
+ export const archiveReadTool = defineTool({
46
+ name: "archive_read",
47
+ group: "archive",
48
+ title: "List or extract an archive",
49
+ description: "List the contents of a .zip/.tar/.tar.gz, or extract entries to a directory. Start with action 'list' to see what is inside, then extract only what you need. Encrypted archives are supported with a password. Symlink entries are never created.",
50
+ inputSchema: {
51
+ path: z.string().min(1).describe("Archive path, relative to the server root."),
52
+ action: z
53
+ .enum(["list", "extract"])
54
+ .optional()
55
+ .describe("'list' (default) reports the entries; 'extract' writes them to `out`."),
56
+ out: z
57
+ .string()
58
+ .optional()
59
+ .describe("Destination directory for extract, relative to the server root. Created if missing."),
60
+ entries: z
61
+ .array(z.string())
62
+ .optional()
63
+ .describe('Extract only these entry paths, or glob-ish prefixes/suffixes such as "data/" or "*.xlsx". Omit to extract everything.'),
64
+ password: z.string().optional().describe("Password for an encrypted archive."),
65
+ overwrite: z
66
+ .boolean()
67
+ .optional()
68
+ .describe("Replace files that already exist in `out`. Defaults to false so an extraction cannot silently clobber a working directory."),
69
+ format: z
70
+ .enum(["zip", "tar"])
71
+ .optional()
72
+ .describe("Container format. Inferred from the extension when omitted.")
73
+ },
74
+ // destructiveHint: extraction replaces files that already exist at the
75
+ // destination, which a client should be able to warn about.
76
+ annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
77
+ // Listing is read-only and useful on a read-only server; extraction calls
78
+ // assertWritable before touching disk. MCP annotations cannot vary by action,
79
+ // so they conservatively describe the destructive branch.
80
+ mutates: false,
81
+ handler: async (args, context) => {
82
+ const { config } = context;
83
+ const archivePath = await resolveInRoot(config, args.path, { mustExist: true });
84
+ const action = args.action ?? "list";
85
+ // Before opening: the reader loads the container into memory, and a .tar.gz
86
+ // is inflated during that call, so a bomb must be refused on its on-disk
87
+ // size first — checking the declared entry sizes afterwards is too late.
88
+ const archiveBytes = (await stat(archivePath)).size;
89
+ if (archiveBytes > config.maxFileSize) {
90
+ throw toolError.tooLarge(`${args.path} is ${formatBytes(archiveBytes)}, over the ${formatBytes(config.maxFileSize)} limit`, "Ask the user to raise --max-file-size if this archive is genuinely needed.");
91
+ }
92
+ const archive = await open(archivePath, args.path, args.format, args.password);
93
+ const entries = await archive.getEntries();
94
+ if (action === "list") {
95
+ return textResult(config, describeEntries(args.path, entries));
96
+ }
97
+ assertWritable(config);
98
+ if (args.out === undefined) {
99
+ throw toolError.invalidInput("extract requires `out`", 'Pass a destination directory, e.g. out: "extracted".');
100
+ }
101
+ let selected = args.entries === undefined
102
+ ? entries
103
+ : entries.filter(entry => matches(entry.path, args.entries ?? []));
104
+ if (selected.length === 0) {
105
+ throw toolError.invalidInput(`no entries matched ${JSON.stringify(args.entries)}`, `The archive contains: ${entries
106
+ .slice(0, 20)
107
+ .map(entry => entry.path)
108
+ .join(", ")}`);
109
+ }
110
+ assertNoBomb(selected, config);
111
+ // ArchiveFile's format-neutral entry type loses ZIP's file/symlink bit.
112
+ // Recover it from the public streaming reader, or a ZIP symlink is exposed
113
+ // as an ordinary 11-byte file and would be written despite our "skip
114
+ // special entries" promise.
115
+ const special = inferFormat(archivePath) === "zip"
116
+ ? await zipSpecialEntries(archivePath, args.password)
117
+ : tarSpecialEntries(entries);
118
+ selected = selected.filter(entry => !special.has(entry.path));
119
+ // Validate the destination directory itself, even when no entry ends up
120
+ // being written: `out: "../elsewhere"` must fail rather than silently
121
+ // succeed on an archive that happens to contain only directories.
122
+ const target = await resolveOutputPath(config, args.out);
123
+ const warnings = [];
124
+ let written = 0;
125
+ let bytesWritten = 0;
126
+ // Validate every destination and overwrite decision before reading or
127
+ // writing the first byte. This prevents a late traversal entry from leaving
128
+ // earlier existing files replaced.
129
+ const destinations = new Map();
130
+ for (const entry of selected) {
131
+ if (entry.isDirectory) {
132
+ continue;
133
+ }
134
+ try {
135
+ const destination = await resolveOutputPath(config, path.posix.join(args.out, entry.path));
136
+ if (args.overwrite !== true && (await exists(destination))) {
137
+ throw toolError.invalidInput(`extraction would overwrite ${path.posix.join(args.out, entry.path)}`, "Pass overwrite: true to replace existing files, or choose an empty destination. Nothing was written.");
138
+ }
139
+ destinations.set(entry.path, destination);
140
+ }
141
+ catch (cause) {
142
+ if (cause instanceof McpToolError && cause.code === "outside_root") {
143
+ throw toolError.invalidInput(`extraction aborted: entry ${JSON.stringify(entry.path)} would be written outside the server root`, "Either the archive contains a traversal path, or the destination directory contains a symlink that leaves the sandbox. Nothing was written.");
144
+ }
145
+ throw cause;
146
+ }
147
+ }
148
+ // Decrypt/decompress every selected entry into a private staging directory
149
+ // before installing any output. A wrong password or corrupt late entry can
150
+ // then fail without leaving a half-extracted tree.
151
+ await ensureParent(target);
152
+ const staging = await mkdtemp(path.join(path.dirname(target), ".documonster-extract-"));
153
+ try {
154
+ for (const [stagingIndex, entry] of selected.entries()) {
155
+ if (entry.isDirectory) {
156
+ continue;
157
+ }
158
+ let bytes;
159
+ try {
160
+ bytes = await archive.readEntry(entry.path, args.password);
161
+ }
162
+ catch (cause) {
163
+ const message = cause instanceof Error ? cause.message : String(cause);
164
+ throw toolError.unsupported(`could not read entry ${JSON.stringify(entry.path)}: ${message}`, /password|encrypt|decrypt/i.test(message)
165
+ ? "The archive is encrypted; pass `password`. Nothing was written."
166
+ : "Nothing was written.", { cause });
167
+ }
168
+ if (bytes === null) {
169
+ warnings.push(`${entry.path}: no data (skipped)`);
170
+ destinations.delete(entry.path);
171
+ continue;
172
+ }
173
+ // The numeric directory makes duplicate basenames (`a/x.txt`,
174
+ // `b/x.txt`) distinct in staging.
175
+ const staged = path.join(staging, String(stagingIndex), path.basename(entry.path));
176
+ await ensureParent(staged);
177
+ await writeFile(staged, bytes);
178
+ destinations.set(entry.path, `${destinations.get(entry.path)}\0${staged}`);
179
+ bytesWritten += bytes.byteLength;
180
+ }
181
+ for (const encoded of destinations.values()) {
182
+ const separator = encoded.indexOf("\0");
183
+ const destination = encoded.slice(0, separator);
184
+ const staged = encoded.slice(separator + 1);
185
+ await writeWithPolicy(destination, args.overwrite === true, temporary => copyFile(staged, temporary));
186
+ written += 1;
187
+ }
188
+ }
189
+ finally {
190
+ await rm(staging, { recursive: true, force: true });
191
+ }
192
+ const lines = [
193
+ `Extracted **${written}** entr${written === 1 ? "y" : "ies"} from ${args.path} to @output/${args.out}/`,
194
+ `- total written: ${formatBytes(bytesWritten)}`,
195
+ "- symlink and special entries were skipped, and file modes were not preserved",
196
+ "",
197
+ ...selected
198
+ .filter(entry => !entry.isDirectory)
199
+ .slice(0, MAX_LISTED)
200
+ .map(entry => `- \`@output/${path.posix.join(args.out ?? "", entry.path)}\` — ${formatBytes(entry.size)}`)
201
+ ];
202
+ if (selected.length > MAX_LISTED) {
203
+ lines.push(`- [${selected.length - MAX_LISTED} more not listed]`);
204
+ }
205
+ if (warnings.length > 0) {
206
+ lines.push("", "Warnings:", ...warnings.slice(0, 20).map(warning => `- ${warning}`));
207
+ }
208
+ lines.push("", "Inspect an extracted file with doc_inspect before reading it.");
209
+ return textResult(config, lines.join("\n"));
210
+ }
211
+ });
212
+ async function open(archivePath, displayPath, format, password) {
213
+ const resolvedFormat = format ?? inferFormat(archivePath);
214
+ try {
215
+ if (resolvedFormat === "tar") {
216
+ return await ArchiveFile.fromFile(archivePath, { format: "tar" });
217
+ }
218
+ return await ArchiveFile.fromFile(archivePath, password === undefined ? {} : { password });
219
+ }
220
+ catch (cause) {
221
+ throw toolError.unsupported(`could not open ${displayPath} as a ${resolvedFormat} archive`, "Run doc_inspect to confirm the container format, and pass `format` explicitly if the extension is misleading.", { cause });
222
+ }
223
+ }
224
+ /** `.tar` / `.tgz` / `.tar.gz` are tar; everything else is treated as zip. */
225
+ function inferFormat(archivePath) {
226
+ const lower = archivePath.toLowerCase();
227
+ return lower.endsWith(".tar") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz")
228
+ ? "tar"
229
+ : "zip";
230
+ }
231
+ /** Entry paths whose ZIP type is not a regular file or directory. */
232
+ async function zipSpecialEntries(archivePath, password) {
233
+ const reader = Archive.unzip(new Uint8Array(await readFile(archivePath)), {
234
+ ...(password === undefined ? {} : { password })
235
+ });
236
+ const special = new Set();
237
+ for await (const entry of reader.entries()) {
238
+ if (entry.type !== "file" && entry.type !== "directory") {
239
+ special.add(entry.path);
240
+ }
241
+ entry.discard();
242
+ }
243
+ return special;
244
+ }
245
+ /** TAR exposes its special-entry type on the format-neutral info object. */
246
+ function tarSpecialEntries(entries) {
247
+ return new Set(entries
248
+ .filter(entry => {
249
+ const type = entry.type;
250
+ return type !== undefined && type !== "file" && type !== "directory";
251
+ })
252
+ .map(entry => entry.path));
253
+ }
254
+ function describeEntries(displayPath, entries) {
255
+ const files = entries.filter(entry => !entry.isDirectory);
256
+ const lines = [
257
+ `# Archive: ${displayPath}`,
258
+ "",
259
+ `- entries: ${entries.length} (${files.length} file(s))`,
260
+ `- total uncompressed: ${formatBytes(totalSize(files))}`,
261
+ ""
262
+ ];
263
+ lines.push("| entry | size |", "| --- | --- |");
264
+ for (const entry of entries.slice(0, MAX_LISTED)) {
265
+ lines.push(`| \`${entry.path}${entry.isDirectory ? "/" : ""}\` | ${entry.isDirectory ? "—" : formatBytes(entry.size)} |`);
266
+ }
267
+ if (entries.length > MAX_LISTED) {
268
+ lines.push("", `[${entries.length - MAX_LISTED} more entries not listed]`);
269
+ }
270
+ lines.push("", 'Extract what you need with `action: "extract"` and an `out` directory.');
271
+ return lines.join("\n");
272
+ }
273
+ function totalSize(entries) {
274
+ return entries.reduce((sum, entry) => sum + (entry.isDirectory ? 0 : entry.size), 0);
275
+ }
276
+ /**
277
+ * Refuse a decompression bomb before writing anything.
278
+ *
279
+ * Sizes come from the archive's own directory, so a lying archive could still
280
+ * under-report; the per-entry check against `--max-file-size` limits the damage
281
+ * a single entry can do, and the total is what stops a thousand small ones.
282
+ */
283
+ function assertNoBomb(entries, config) {
284
+ if (entries.length > MAX_ENTRIES) {
285
+ throw toolError.tooLarge(`the selection has ${entries.length} entries, over the ${MAX_ENTRIES} limit`, "Narrow the `entries` filter to the files you actually need.");
286
+ }
287
+ const total = totalSize(entries);
288
+ if (total > MAX_TOTAL_EXTRACTED) {
289
+ throw toolError.tooLarge(`extracting would write ${formatBytes(total)}, over the ${formatBytes(MAX_TOTAL_EXTRACTED)} limit`, "Narrow the `entries` filter.");
290
+ }
291
+ for (const entry of entries) {
292
+ if (!entry.isDirectory && entry.size > config.maxFileSize) {
293
+ throw toolError.tooLarge(`entry ${JSON.stringify(entry.path)} is ${formatBytes(entry.size)}, over the per-file limit of ${formatBytes(config.maxFileSize)}`, "Exclude it, or ask the user to raise --max-file-size.");
294
+ }
295
+ }
296
+ }
297
+ /**
298
+ * Match an entry against caller-supplied selectors.
299
+ *
300
+ * Supports exact paths, `dir/` prefixes and `*.ext` suffixes — the three shapes
301
+ * a model reaches for. Not a full glob, and deliberately so: a half-working
302
+ * glob is worse than a documented small set.
303
+ */
304
+ function matches(entryPath, selectors) {
305
+ return selectors.some(selector => {
306
+ if (selector.startsWith("*.")) {
307
+ return entryPath.toLowerCase().endsWith(selector.slice(1).toLowerCase());
308
+ }
309
+ if (selector.endsWith("/")) {
310
+ return entryPath.startsWith(selector);
311
+ }
312
+ return entryPath === selector;
313
+ });
314
+ }
315
+ //# sourceMappingURL=archive-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-read.js","sourceRoot":"","sources":["../../src/tools/archive-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `archive_write` — package files into an archive.
3
+ *
4
+ * Closes the loop that `archive_read` opens. A session that unpacked an archive,
5
+ * analysed it and produced several outputs needs to hand back one file, and a
6
+ * model cannot assemble a binary container itself. Small tool, high value.
7
+ */
8
+ export declare const archiveWriteTool: import("./types.js").AnyToolDefinition;
9
+ //# sourceMappingURL=archive-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-write.d.ts","sourceRoot":"","sources":["../../src/tools/archive-write.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,eAAO,MAAM,gBAAgB,wCA8H3B,CAAC"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * `archive_write` — package files into an archive.
3
+ *
4
+ * Closes the loop that `archive_read` opens. A session that unpacked an archive,
5
+ * analysed it and produced several outputs needs to hand back one file, and a
6
+ * model cannot assemble a binary container itself. Small tool, high value.
7
+ */
8
+ import { readdir, stat } from "node:fs/promises";
9
+ import path from "node:path";
10
+ import { ArchiveFile } from "documonster/archive";
11
+ import { z } from "zod";
12
+ import { toolError } from "../errors.js";
13
+ import { assertWritable, outputDisplay, resolveInRoot, resolveOutputPath } from "../sandbox.js";
14
+ import { writeWithPolicy } from "./fs-helpers.js";
15
+ import { formatBytes, textResult } from "./result.js";
16
+ import { defineTool } from "./types.js";
17
+ /** Files one archive may contain. */
18
+ const MAX_FILES = 5_000;
19
+ /** Total input bytes allowed in one archive (512 MiB). */
20
+ const MAX_TOTAL_INPUT = 512 * 1024 * 1024;
21
+ export const archiveWriteTool = defineTool({
22
+ name: "archive_write",
23
+ group: "archive",
24
+ title: "Create an archive",
25
+ description: "Package files and directories into a .zip or .tar. Use it to hand a set of produced documents back as one file. Directories are added recursively. Every input must be inside the server root.",
26
+ inputSchema: {
27
+ out: z
28
+ .string()
29
+ .min(1)
30
+ .describe("Archive path to create below --output-root. The result is returned as @output/<path>. The extension chooses .zip or .tar."),
31
+ entries: z
32
+ .array(z.object({
33
+ path: z
34
+ .string()
35
+ .min(1)
36
+ .describe("File or directory to add, relative to the server root."),
37
+ as: z
38
+ .string()
39
+ .optional()
40
+ .describe("Name inside the archive. For a directory this is the prefix. Defaults to the base name.")
41
+ }))
42
+ .min(1)
43
+ .describe("Files and directories to include."),
44
+ overwrite: z
45
+ .boolean()
46
+ .optional()
47
+ .describe("Replace the archive if it exists. Defaults to false.")
48
+ },
49
+ annotations: {
50
+ readOnlyHint: false,
51
+ destructiveHint: false,
52
+ idempotentHint: false,
53
+ openWorldHint: false
54
+ },
55
+ mutates: true,
56
+ handler: async (args, context) => {
57
+ const { config } = context;
58
+ assertWritable(config);
59
+ const format = formatFor(args.out);
60
+ const target = await resolveOutputPath(config, args.out);
61
+ // Resolve and measure everything before creating the archive, so a bad
62
+ // entry fails before any file is written.
63
+ //
64
+ // Entry names are validated too: an archive is data we hand to someone else,
65
+ // and `as: "../../escape.txt"` would make this tool the *producer* of a Zip
66
+ // Slip payload. Neither the ZIP nor the TAR writer rejects it.
67
+ const resolvedEntries = await Promise.all(args.entries.map(async (entry) => {
68
+ const resolved = await resolveInRoot(config, entry.path, { mustExist: true });
69
+ const stats = await stat(resolved);
70
+ return {
71
+ resolved,
72
+ display: entry.path,
73
+ name: assertSafeEntryName(entry.as ?? path.basename(entry.path)),
74
+ isDirectory: stats.isDirectory(),
75
+ size: stats.isDirectory() ? 0 : stats.size
76
+ };
77
+ }));
78
+ await assertWithinBudget(resolvedEntries, config);
79
+ // Branch rather than holding a union: ArchiveFile is generic in its format,
80
+ // and `ArchiveFile<"zip"> | ArchiveFile<"tar">` collapses to `never` on any
81
+ // shared method because the `format` field conflicts.
82
+ try {
83
+ // "overwrite" is safe here only because the archive is built into a
84
+ // temporary sibling and renamed into place; the caller's `overwrite: false`
85
+ // was enforced above, and the rename is what makes the replacement atomic
86
+ // rather than a truncate-then-fill.
87
+ await writeWithPolicy(target, args.overwrite === true, async (temporary) => {
88
+ if (format === "tar") {
89
+ const archive = new ArchiveFile({ format: "tar" });
90
+ addAll(archive, resolvedEntries);
91
+ await archive.writeToFile(temporary, { overwrite: "overwrite" });
92
+ }
93
+ else {
94
+ const archive = new ArchiveFile();
95
+ addAll(archive, resolvedEntries);
96
+ await archive.writeToFile(temporary, { overwrite: "overwrite" });
97
+ }
98
+ });
99
+ }
100
+ catch (cause) {
101
+ throw toolError.unsupported(`could not write the archive: ${cause instanceof Error ? cause.message : String(cause)}`, undefined, { cause });
102
+ }
103
+ // Read it back and report the real entry list — "wrote 4 KB" says nothing
104
+ // about whether the archive contains what was intended.
105
+ const entries = format === "tar"
106
+ ? await (await ArchiveFile.fromFile(target, { format: "tar" })).getEntries()
107
+ : await (await ArchiveFile.fromFile(target)).getEntries();
108
+ const files = entries.filter(entry => !entry.isDirectory);
109
+ const size = (await stat(target)).size;
110
+ return textResult(config, [
111
+ `Created **${outputDisplay(args.out)}** (${format}, ${formatBytes(size)}) containing ${files.length} file(s).`,
112
+ "",
113
+ "| entry | size |",
114
+ "| --- | --- |",
115
+ ...entries
116
+ .slice(0, 200)
117
+ .map(entry => `| \`${entry.path}${entry.isDirectory ? "/" : ""}\` | ${entry.isDirectory ? "—" : formatBytes(entry.size)} |`),
118
+ ...(entries.length > 200 ? ["", `[${entries.length - 200} more not listed]`] : []),
119
+ "",
120
+ "Verified by reading the archive back."
121
+ ].join("\n"));
122
+ }
123
+ });
124
+ /**
125
+ * Reject an archive entry name that would escape on extraction.
126
+ *
127
+ * Absolute paths, `..` segments and Windows drive letters are all refused, and
128
+ * separators are normalised to the forward slashes an archive uses.
129
+ */
130
+ function assertSafeEntryName(name) {
131
+ const normalised = name.replace(/\\/g, "/").replace(/^\/+/, "").trim();
132
+ if (normalised.length === 0) {
133
+ throw toolError.invalidInput("an entry name cannot be empty");
134
+ }
135
+ if (/^[a-zA-Z]:/.test(normalised)) {
136
+ throw toolError.invalidInput(`entry name ${JSON.stringify(name)} must not be an absolute Windows path`);
137
+ }
138
+ if (normalised.split("/").some(segment => segment === "..")) {
139
+ throw toolError.invalidInput(`entry name ${JSON.stringify(name)} must not contain ".."`, "Entry names are relative paths inside the archive. A `..` would make the archive unsafe for whoever extracts it.");
140
+ }
141
+ return normalised;
142
+ }
143
+ /** `.tar` is tar; `.zip` is zip; anything else is rejected by name. */
144
+ function formatFor(out) {
145
+ const extension = path.extname(out).toLowerCase();
146
+ if (extension === ".tar") {
147
+ return "tar";
148
+ }
149
+ if (extension === ".zip") {
150
+ return "zip";
151
+ }
152
+ throw toolError.invalidInput(`cannot tell the archive format from ${JSON.stringify(out)}`, "Use a .zip or .tar extension. Compressed tarballs (.tar.gz) are not produced yet.");
153
+ }
154
+ /** Add every entry to an archive of either format. */
155
+ function addAll(archive, entries) {
156
+ for (const entry of entries) {
157
+ if (entry.isDirectory) {
158
+ archive.addDirectory(entry.resolved, { prefix: entry.name });
159
+ }
160
+ else {
161
+ archive.addFile(entry.resolved, { name: entry.name });
162
+ }
163
+ }
164
+ }
165
+ /**
166
+ * Refuse an archive that would read too much.
167
+ *
168
+ * Directories are walked to measure them, because "add this directory" is how a
169
+ * caller accidentally packages a whole workspace.
170
+ */
171
+ async function assertWithinBudget(entries, config) {
172
+ let total = 0;
173
+ let count = 0;
174
+ for (const entry of entries) {
175
+ if (entry.isDirectory) {
176
+ // The per-file cap applies inside a directory as well: "add this folder"
177
+ // is exactly how a caller accidentally packages one enormous file.
178
+ const walked = await measureDirectory(entry.resolved, config, entry.display);
179
+ total += walked.bytes;
180
+ count += walked.files;
181
+ }
182
+ else {
183
+ if (entry.size > config.maxFileSize) {
184
+ throw toolError.tooLarge(`${entry.display} is ${formatBytes(entry.size)}, over the per-file limit of ${formatBytes(config.maxFileSize)}`, "Exclude it, or ask the user to raise --max-file-size.");
185
+ }
186
+ total += entry.size;
187
+ count += 1;
188
+ }
189
+ if (count > MAX_FILES) {
190
+ throw toolError.tooLarge(`the selection contains more than ${MAX_FILES} files`, "Name specific files or a narrower directory.");
191
+ }
192
+ if (total > MAX_TOTAL_INPUT) {
193
+ throw toolError.tooLarge(`the selection totals more than ${formatBytes(MAX_TOTAL_INPUT)}`, "Name specific files or a narrower directory.");
194
+ }
195
+ }
196
+ }
197
+ async function measureDirectory(dir, config, display) {
198
+ let bytes = 0;
199
+ let files = 0;
200
+ const walk = async (current) => {
201
+ for (const item of await readdir(current, { withFileTypes: true })) {
202
+ const full = path.join(current, item.name);
203
+ if (item.isDirectory()) {
204
+ await walk(full);
205
+ }
206
+ else if (item.isFile()) {
207
+ const size = (await stat(full)).size;
208
+ if (size > config.maxFileSize) {
209
+ throw toolError.tooLarge(`${display}/${path.relative(dir, full)} is ${formatBytes(size)}, over the per-file limit of ${formatBytes(config.maxFileSize)}`, "Name specific files instead of the whole directory, or ask the user to raise --max-file-size.");
210
+ }
211
+ files += 1;
212
+ bytes += size;
213
+ }
214
+ }
215
+ };
216
+ await walk(dir);
217
+ return { bytes, files };
218
+ }
219
+ //# sourceMappingURL=archive-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-write.js","sourceRoot":"","sources":["../../src/tools/archive-write.ts"],"names":[],"mappings":"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"}