@j0hanz/filesystem-mcp 2.8.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -26
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +10 -1
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/concurrency.d.ts +4 -4
- package/dist/core/concurrency.d.ts.map +1 -1
- package/dist/core/concurrency.js +1 -1
- package/dist/core/concurrency.js.map +1 -1
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/file-uri.d.ts +12 -3
- package/dist/core/file-uri.d.ts.map +1 -1
- package/dist/core/file-uri.js +35 -7
- package/dist/core/file-uri.js.map +1 -1
- package/dist/core/fmt.d.ts +2 -0
- package/dist/core/fmt.d.ts.map +1 -1
- package/dist/core/fmt.js +16 -0
- package/dist/core/fmt.js.map +1 -1
- package/dist/core/fs.d.ts +16 -1
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +127 -32
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +8 -0
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +84 -11
- package/dist/core/glob.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +5 -3
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path-utils.d.ts +42 -6
- package/dist/core/path-utils.d.ts.map +1 -1
- package/dist/core/path-utils.js +56 -10
- package/dist/core/path-utils.js.map +1 -1
- package/dist/core/path.d.ts +111 -7
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +453 -65
- package/dist/core/path.js.map +1 -1
- package/dist/core/read.d.ts +6 -0
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +26 -3
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts +9 -6
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +22 -19
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +6 -0
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +159 -33
- package/dist/core/search.js.map +1 -1
- package/dist/core/sensitive.d.ts.map +1 -1
- package/dist/core/sensitive.js +64 -15
- package/dist/core/sensitive.js.map +1 -1
- package/dist/core/store.d.ts +1 -0
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +3 -0
- package/dist/core/store.js.map +1 -1
- package/dist/core/util.d.ts +6 -1
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +8 -1
- package/dist/core/util.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +18 -9
- package/dist/resources.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +121 -43
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +8 -4
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +36 -9
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts.map +1 -1
- package/dist/tools/delete.js +50 -11
- package/dist/tools/delete.js.map +1 -1
- package/dist/tools/diff.js +1 -1
- package/dist/tools/diff.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +14 -12
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +15 -9
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +138 -86
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +72 -26
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.js +13 -6
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +114 -45
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +49 -35
- package/dist/tools/replace-text.js.map +1 -1
- package/dist/tools/search-text.d.ts.map +1 -1
- package/dist/tools/search-text.js +15 -33
- package/dist/tools/search-text.js.map +1 -1
- package/dist/tools/stat.d.ts.map +1 -1
- package/dist/tools/stat.js +26 -8
- package/dist/tools/stat.js.map +1 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +1 -0
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/stdio.js +1 -1
- package/dist/transport/stdio.js.map +1 -1
- package/package.json +5 -5
package/dist/tools/read.js
CHANGED
|
@@ -4,9 +4,10 @@ import * as z from 'zod/v4';
|
|
|
4
4
|
import { processInParallel } from "../core/concurrency.js";
|
|
5
5
|
import { ErrorCode, FsError } from "../core/errors.js";
|
|
6
6
|
import { buildFileResourceLinkFor, buildFileResourceUri } from "../core/file-uri.js";
|
|
7
|
-
import { detectMimeFromContent, detectMimeType } from "../core/mime.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { detectMimeFromContent, detectMimeType, isKnownBinaryExtension, } from "../core/mime.js";
|
|
8
|
+
import { BINARY_FILE_MESSAGE, isBinaryRefusal, } from "../core/read.js";
|
|
9
|
+
import { defaultFalseBoolean, mapSingleOrBatchPaths, singleOrBatchPathsInput, validateReadRange, } from "../core/schema.js";
|
|
10
|
+
import { DEFAULT_CONTINUATION_CHUNK_SIZE, getMaxTextFileSize, PARALLEL_CONCURRENCY, READ_MANY_MAX_TOTAL_BYTES, } from "../core/util.js";
|
|
10
11
|
import { isTotalFailure, runOverPaths } from "./batch.js";
|
|
11
12
|
import { defineTool } from "./define.js";
|
|
12
13
|
/**
|
|
@@ -24,35 +25,34 @@ const readRangeFields = {
|
|
|
24
25
|
head: rangeField('Return first N lines', true),
|
|
25
26
|
tail: rangeField('Return last N lines', true),
|
|
26
27
|
startLine: rangeField('Start line (1-indexed)'),
|
|
27
|
-
endLine: rangeField('End line (1-indexed)'),
|
|
28
|
+
endLine: rangeField('End line (1-indexed); requires startLine'),
|
|
28
29
|
};
|
|
30
|
+
/** A slice read: only a full read returns media or a binary resource. */
|
|
31
|
+
function hasLineRange(args) {
|
|
32
|
+
return (args.head !== undefined ||
|
|
33
|
+
args.tail !== undefined ||
|
|
34
|
+
args.startLine !== undefined ||
|
|
35
|
+
args.endLine !== undefined);
|
|
36
|
+
}
|
|
29
37
|
const ReadFileInputSchema = singleOrBatchPathsInput({
|
|
30
38
|
includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),
|
|
39
|
+
binary: defaultFalseBoolean('Return a binary file that is not an image or audio whole, as a base64 embedded resource. Full reads only.'),
|
|
31
40
|
...readRangeFields,
|
|
32
|
-
})
|
|
33
|
-
.superRefine((value, ctx) => {
|
|
41
|
+
}).superRefine((value, ctx) => {
|
|
34
42
|
validateReadRange({
|
|
35
43
|
head: value.head,
|
|
36
44
|
tail: value.tail,
|
|
37
45
|
startLine: value.startLine,
|
|
38
46
|
endLine: value.endLine,
|
|
39
47
|
}, ctx);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.meta({
|
|
49
|
-
// The line-param exclusivity that used to sit here as a five-branch
|
|
50
|
-
// `not/anyOf` is one sentence in the description instead: validateReadRange
|
|
51
|
-
// rejects every conflicting combination by name at runtime, so the wire copy
|
|
52
|
-
// was paying for a second statement of a rule the model reads better in
|
|
53
|
-
// prose.
|
|
54
|
-
oneOf: [{ required: ['path'] }, { required: ['paths'] }],
|
|
55
|
-
dependentRequired: { endLine: ['startLine'] },
|
|
48
|
+
if (value.binary && hasLineRange(value)) {
|
|
49
|
+
ctx.addIssue({
|
|
50
|
+
code: 'custom',
|
|
51
|
+
path: ['binary'],
|
|
52
|
+
message: "Cannot use 'binary' with 'head'/'tail'/'startLine'/'endLine'. A binary file is read whole.",
|
|
53
|
+
input: value,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
56
|
});
|
|
57
57
|
const READ_TOOL_LABEL = 'Read';
|
|
58
58
|
function buildReadSpec(args, signal) {
|
|
@@ -99,12 +99,23 @@ function buildReadContinuation(result, requestedPath) {
|
|
|
99
99
|
hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
/**
|
|
103
|
+
* What a file costs the batch: one whose bytes ship as base64 costs that size.
|
|
104
|
+
* Only a full read ships base64; a slice of an svg is text.
|
|
105
|
+
*/
|
|
106
|
+
function budgetBytes(path, size, { fullRead, binary }) {
|
|
107
|
+
if (!fullRead)
|
|
108
|
+
return size;
|
|
109
|
+
const { kind } = detectMimeType(path);
|
|
110
|
+
const base64 = kind === 'image' || kind === 'audio' || (binary && isKnownBinaryExtension(path));
|
|
111
|
+
return base64 ? 4 * Math.ceil(size / 3) : size;
|
|
112
|
+
}
|
|
113
|
+
async function collectFileBudget(filePaths, maxTotalSize, maxSize, ctx, mode) {
|
|
103
114
|
const indexed = filePaths.map((path, index) => ({ path, index }));
|
|
104
115
|
const { results } = await processInParallel(indexed, async ({ path, index }) => {
|
|
105
116
|
try {
|
|
106
117
|
const out = await ctx.fs.stat(path);
|
|
107
|
-
return { index, size: Math.min(out.stats.size, maxSize) };
|
|
118
|
+
return { index, size: budgetBytes(path, Math.min(out.stats.size, maxSize), mode) };
|
|
108
119
|
}
|
|
109
120
|
catch (err) {
|
|
110
121
|
ctx.log('debug', `collectFileBudget: stat failed for "${path}": ${String(err)}`, 'read');
|
|
@@ -142,8 +153,10 @@ function buildPerPathReadValue(result, options) {
|
|
|
142
153
|
const contentHash = options.includeHash
|
|
143
154
|
? createHash('sha256').update(result.content, 'utf-8').digest('hex')
|
|
144
155
|
: undefined;
|
|
156
|
+
const canLink = result.fileSize === undefined || result.fileSize <= getMaxTextFileSize();
|
|
145
157
|
return {
|
|
146
158
|
content: result.content,
|
|
159
|
+
...(result.fileSize !== undefined ? { fileSize: result.fileSize } : {}),
|
|
147
160
|
mimeType: mimeInfo.mimeType,
|
|
148
161
|
kind: mimeInfo.kind,
|
|
149
162
|
...(continuation ? { continuation } : {}),
|
|
@@ -155,7 +168,7 @@ function buildPerPathReadValue(result, options) {
|
|
|
155
168
|
...(result.startLine !== undefined ? { startLine: result.startLine } : {}),
|
|
156
169
|
...(result.endLine !== undefined ? { endLine: result.endLine } : {}),
|
|
157
170
|
...(contentHash !== undefined ? { contentHash } : {}),
|
|
158
|
-
resourceUri: buildFileResourceUri(result.path),
|
|
171
|
+
...(canLink ? { resourceUri: buildFileResourceUri(result.path) } : {}),
|
|
159
172
|
modified: result.modified,
|
|
160
173
|
};
|
|
161
174
|
}
|
|
@@ -180,17 +193,39 @@ function readTrailer(v) {
|
|
|
180
193
|
lines.push(`// sha256: ${v.contentHash}`);
|
|
181
194
|
return lines;
|
|
182
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* `binary: true` after the text path refused the file as binary. readRaw
|
|
198
|
+
* re-validates the path (roots, denylist) and enforces the same size cap.
|
|
199
|
+
* A file refused by its extension can still probe as text: it ships as the
|
|
200
|
+
* extension says, octet-stream.
|
|
201
|
+
*/
|
|
202
|
+
async function readBinaryResource(filePath, args, ctx) {
|
|
203
|
+
const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });
|
|
204
|
+
const asText = raw.kind === 'text';
|
|
205
|
+
const kind = asText ? 'binary' : raw.kind;
|
|
206
|
+
const mimeType = asText ? 'application/octet-stream' : raw.mimeType;
|
|
207
|
+
const size = raw.content.length;
|
|
208
|
+
return {
|
|
209
|
+
content: `[binary ${kind} content: ${String(size)} bytes (${mimeType}); returned as an embedded resource block]`,
|
|
210
|
+
mimeType,
|
|
211
|
+
kind,
|
|
212
|
+
size,
|
|
213
|
+
resourceUri: buildFileResourceUri(raw.validPath),
|
|
214
|
+
modified: raw.modified,
|
|
215
|
+
blobData: raw.content.toString('base64'),
|
|
216
|
+
...(args.includeHash
|
|
217
|
+
? { contentHash: createHash('sha256').update(raw.content).digest('hex') }
|
|
218
|
+
: {}),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
183
221
|
async function readOnePath(filePath, args, ctx) {
|
|
184
222
|
// Image/audio full read: return a media content block instead of throwing
|
|
185
223
|
// INVALID_INPUT ("Binary file detected."). Line-range reads are
|
|
186
224
|
// text-oriented and stay rejected. `readRaw` enforces the same size cap as
|
|
187
225
|
// the text path (getMaxTextFileSize), so a too-large image surfaces TOO_LARGE
|
|
188
|
-
// rather than blowing memory. svg
|
|
189
|
-
//
|
|
190
|
-
const isRangeRead = args
|
|
191
|
-
args.tail !== undefined ||
|
|
192
|
-
args.startLine !== undefined ||
|
|
193
|
-
args.endLine !== undefined;
|
|
226
|
+
// rather than blowing memory. svg is kind 'image' in EXT_MAP, so readRaw
|
|
227
|
+
// reports it binary and it returns as an image block.
|
|
228
|
+
const isRangeRead = hasLineRange(args);
|
|
194
229
|
if (!isRangeRead) {
|
|
195
230
|
const mime = detectMimeType(filePath);
|
|
196
231
|
if (mime.kind === 'image' || mime.kind === 'audio') {
|
|
@@ -200,7 +235,13 @@ async function readOnePath(filePath, args, ctx) {
|
|
|
200
235
|
content: `[binary ${mime.kind} content: ${String(raw.content.length)} bytes; returned as a ${mime.kind} content block]`,
|
|
201
236
|
mimeType: raw.mimeType,
|
|
202
237
|
kind: mime.kind,
|
|
238
|
+
size: raw.content.length,
|
|
239
|
+
resourceUri: buildFileResourceUri(raw.validPath),
|
|
240
|
+
modified: raw.modified,
|
|
203
241
|
mediaData: raw.content.toString('base64'),
|
|
242
|
+
...(args.includeHash
|
|
243
|
+
? { contentHash: createHash('sha256').update(raw.content).digest('hex') }
|
|
244
|
+
: {}),
|
|
204
245
|
};
|
|
205
246
|
}
|
|
206
247
|
}
|
|
@@ -208,12 +249,26 @@ async function readOnePath(filePath, args, ctx) {
|
|
|
208
249
|
const spec = buildReadSpec(args, ctx.signal);
|
|
209
250
|
// The read re-validates and re-stats: the budget pass's stat is only a
|
|
210
251
|
// size estimate, never a substitute for the guarded open.
|
|
211
|
-
|
|
252
|
+
let result;
|
|
253
|
+
try {
|
|
254
|
+
result = await ctx.fs.readFile(filePath, spec);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
if (!isBinaryRefusal(error))
|
|
258
|
+
throw error;
|
|
259
|
+
// The schema refuses binary with a range, so this is always a full read.
|
|
260
|
+
if (args.binary)
|
|
261
|
+
return await readBinaryResource(filePath, args, ctx);
|
|
262
|
+
throw new FsError(ErrorCode.INVALID_INPUT, isRangeRead
|
|
263
|
+
? `${BINARY_FILE_MESSAGE} It has no lines; read it whole with binary: true to get it as a base64 embedded resource.`
|
|
264
|
+
: `${BINARY_FILE_MESSAGE} Pass binary: true to get it as a base64 embedded resource.`, filePath, error);
|
|
265
|
+
}
|
|
212
266
|
return buildPerPathReadValue(result, {
|
|
213
267
|
includeHash: args.includeHash,
|
|
214
268
|
// The continuation is args the caller pastes back, so it echoes the path
|
|
215
|
-
// they wrote
|
|
216
|
-
// is
|
|
269
|
+
// they wrote, or the root-resolved one a relative path was rewritten to.
|
|
270
|
+
// `result.path` is the real path — on Windows that is a backslash-doubling
|
|
271
|
+
// JSON string that also spells out the server root.
|
|
217
272
|
requestedPath: filePath,
|
|
218
273
|
});
|
|
219
274
|
}
|
|
@@ -221,10 +276,10 @@ export const READ = defineTool({
|
|
|
221
276
|
name: 'read',
|
|
222
277
|
title: 'Read File',
|
|
223
278
|
description: 'Read text files, like cat: whole, or one slice via head, tail, or startLine/endLine. ' +
|
|
224
|
-
'Images and audio return as media; other binary
|
|
279
|
+
'Images and audio return as media; pass binary: true to get any other binary file whole as a base64 embedded resource.',
|
|
225
280
|
input: ReadFileInputSchema,
|
|
226
281
|
readOnlyHint: true,
|
|
227
|
-
|
|
282
|
+
deadline: true,
|
|
228
283
|
defaultErrorCode: ErrorCode.NOT_FILE,
|
|
229
284
|
progress: (args) => {
|
|
230
285
|
const isBatch = args.paths !== undefined;
|
|
@@ -245,10 +300,10 @@ export const READ = defineTool({
|
|
|
245
300
|
}
|
|
246
301
|
return { label: READ_TOOL_LABEL, subject: name, ...(scope ? { scope } : {}) };
|
|
247
302
|
},
|
|
248
|
-
|
|
303
|
+
mapPaths: mapSingleOrBatchPaths,
|
|
249
304
|
run: async (args, ctx) => {
|
|
250
305
|
const items = args.paths !== undefined
|
|
251
|
-
? await collectFileBudget(args.paths, READ_MANY_MAX_TOTAL_BYTES, getMaxTextFileSize(), ctx)
|
|
306
|
+
? await collectFileBudget(args.paths, READ_MANY_MAX_TOTAL_BYTES, getMaxTextFileSize(), ctx, { fullRead: !hasLineRange(args), binary: args.binary })
|
|
252
307
|
: [{ path: args.path ?? '' }];
|
|
253
308
|
const { results: ordered, summary } = await runOverPaths(items, ctx, ErrorCode.NOT_FILE, ({ path, skip }) => {
|
|
254
309
|
if (skip)
|
|
@@ -260,6 +315,13 @@ export const READ = defineTool({
|
|
|
260
315
|
if ('error' in result)
|
|
261
316
|
continue;
|
|
262
317
|
const v = result.value;
|
|
318
|
+
if (v.blobData !== undefined && v.resourceUri !== undefined && v.mimeType !== undefined) {
|
|
319
|
+
resources.push({
|
|
320
|
+
type: 'resource',
|
|
321
|
+
resource: { uri: v.resourceUri, mimeType: v.mimeType, blob: v.blobData },
|
|
322
|
+
});
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
263
325
|
// Image/audio full read: emit the media content block alongside the
|
|
264
326
|
// structured value. The base64 lives in v.mediaData (set in readOnePath).
|
|
265
327
|
if (v.mediaData && v.mimeType && (v.kind === 'image' || v.kind === 'audio')) {
|
|
@@ -268,13 +330,13 @@ export const READ = defineTool({
|
|
|
268
330
|
: { type: 'audio', data: v.mediaData, mimeType: v.mimeType });
|
|
269
331
|
continue;
|
|
270
332
|
}
|
|
271
|
-
if (!v.resourceUri ||
|
|
333
|
+
if (!v.resourceUri || v.content === undefined)
|
|
272
334
|
continue;
|
|
273
335
|
// `result.path` is the path as *requested*; `v.resourceUri` was built from
|
|
274
336
|
// the *validated* one. Rebuilding from the request would emit a second URI
|
|
275
337
|
// for the same file whenever the two differ in case — subscribe by one and
|
|
276
338
|
// unsubscribe by the other and the watcher never goes away.
|
|
277
|
-
resources.push(buildFileResourceLinkFor(v.resourceUri, basename(result.path), v.mimeType ?? 'application/octet-stream', Buffer.byteLength(v.content, 'utf8'), v.modified));
|
|
339
|
+
resources.push(buildFileResourceLinkFor(v.resourceUri, basename(result.path), v.mimeType ?? 'application/octet-stream', v.fileSize ?? Buffer.byteLength(v.content, 'utf8'), v.modified));
|
|
278
340
|
}
|
|
279
341
|
const [firstOrdered] = ordered;
|
|
280
342
|
const body = (v) => {
|
|
@@ -307,7 +369,7 @@ export const READ = defineTool({
|
|
|
307
369
|
const structuredResults = ordered.map((result) => {
|
|
308
370
|
if ('error' in result)
|
|
309
371
|
return result;
|
|
310
|
-
const { content: _content, mediaData: _mediaData, ...value } = result.value;
|
|
372
|
+
const { content: _content, fileSize: _fileSize, mediaData: _mediaData, blobData: _blobData, ...value } = result.value;
|
|
311
373
|
return { ...result, value };
|
|
312
374
|
});
|
|
313
375
|
return {
|
|
@@ -317,9 +379,16 @@ export const READ = defineTool({
|
|
|
317
379
|
...(resources.length > 0 ? { resources } : {}),
|
|
318
380
|
};
|
|
319
381
|
},
|
|
320
|
-
// Media cannot be sliced, so head/tail is no remedy
|
|
321
|
-
oversizeRemedy: (result) =>
|
|
322
|
-
|
|
323
|
-
|
|
382
|
+
// Media and binary resources cannot be sliced, so head/tail is no remedy.
|
|
383
|
+
oversizeRemedy: (result) => {
|
|
384
|
+
const types = new Set(result.resources?.map((b) => b.type));
|
|
385
|
+
if (types.has('image') || types.has('audio')) {
|
|
386
|
+
return 'This media file is too large to return over the stdio transport; connect over HTTP, or raise it as a smaller file.';
|
|
387
|
+
}
|
|
388
|
+
if (types.has('resource')) {
|
|
389
|
+
return 'This binary file is too large to return over the stdio transport; connect over HTTP.';
|
|
390
|
+
}
|
|
391
|
+
return 'Read a slice with head, tail, or startLine/endLine.';
|
|
392
|
+
},
|
|
324
393
|
});
|
|
325
394
|
//# sourceMappingURL=read.js.map
|
package/dist/tools/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { createHash } from 'node:crypto';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.ts';\nimport { detectMimeFromContent, detectMimeType, type FileKind } from '../core/mime.ts';\nimport type { ReadFileResult, ReadSpec } from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n singleOrBatchAccessPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.ts';\nimport {\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n DEFAULT_SEARCH_TIMEOUT_MS,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n READ_MANY_MAX_TOTAL_BYTES,\n} from '../core/util.ts';\nimport type { BatchResult } from './batch.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\n/**\n * `z.int32()`'s own ceiling on startLine/endLine, named so a continuation\n * never asks for more. Not restated as `.max()`: that reports it twice.\n */\nconst MAX_LINE_NUMBER = 2_147_483_647;\n\nconst rangeField = (description: string, count = false) => {\n const field = z.int32().min(1, { message: 'Min: 1' });\n return (count ? field.max(100000, { message: 'Max: 100,000' }) : field)\n .optional()\n .describe(description);\n};\n\nconst readRangeFields = {\n head: rangeField('Return first N lines', true),\n tail: rangeField('Return last N lines', true),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed)'),\n};\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n ...readRangeFields,\n})\n .superRefine((value, ctx) => {\n validateReadRange(\n {\n head: value.head,\n tail: value.tail,\n startLine: value.startLine,\n endLine: value.endLine,\n },\n ctx,\n );\n })\n // Mirror `validateReadRange` on the wire. Without this the four line params\n // published as four independent optional integers, so `{ path, head, tail }`\n // passed the advertised schema and was rejected only at call time.\n //\n // `oneOf` is restated because `.meta()` replaces the entry\n // `singleOrBatchPathsInput` set rather than merging into it — dropping it here\n // would silently un-publish the path/paths rule.\n .meta({\n // The line-param exclusivity that used to sit here as a five-branch\n // `not/anyOf` is one sentence in the description instead: validateReadRange\n // rejects every conflicting combination by name at runtime, so the wire copy\n // was paying for a second statement of a rule the model reads better in\n // prose.\n oneOf: [{ required: ['path'] }, { required: ['paths'] }],\n dependentRequired: { endLine: ['startLine'] },\n });\n\ninterface ReadContinuation {\n tool: 'read';\n args: { path: string; startLine: number; endLine: number };\n hint: string;\n}\n\n// File bytes ride content blocks, never the structured metadata.\ninterface ReadPerPathValue {\n mimeType?: string;\n kind?: FileKind;\n resourceUri?: string;\n /** ISO-8601 mtime at read time; also rides the resource_link. */\n modified?: string;\n continuation?: ReadContinuation;\n totalLines?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n contentHash?: string;\n}\n\ntype ReadFileInput = z.infer<typeof ReadFileInputSchema>;\n\nconst READ_TOOL_LABEL = 'Read';\n\nfunction buildReadSpec(args: ReadFileInput, signal?: AbortSignal): ReadSpec {\n const signalPart = signal ? { signal } : {};\n const { head, tail, startLine, endLine } = args;\n\n if (head !== undefined) return { kind: 'head', lines: head, ...signalPart };\n if (tail !== undefined) return { kind: 'tail', lines: tail, ...signalPart };\n if (startLine !== undefined || endLine !== undefined) {\n return {\n kind: 'range',\n start: startLine ?? 1,\n ...(endLine !== undefined ? { end: endLine } : {}),\n ...signalPart,\n };\n }\n return { kind: 'full', ...signalPart };\n}\n\n// No `totalLines`: only `readFull` counts them and a full read never leaves\n// more behind, so a continuation cannot know the total without a second pass.\nfunction buildReadContinuation(\n result: ReadFileResult,\n requestedPath: string,\n): ReadContinuation | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\n // Args the schema would reject are no continuation; clamp the end into it.\n if (nextStart > MAX_LINE_NUMBER) return undefined;\n let chunkSize: number;\n if (result.head !== undefined) {\n chunkSize = result.head;\n } else if (result.startLine !== undefined && result.endLine !== undefined) {\n chunkSize = result.endLine - result.startLine + 1;\n } else {\n chunkSize = DEFAULT_CONTINUATION_CHUNK_SIZE;\n }\n const nextEnd = Math.min(nextStart + chunkSize - 1, MAX_LINE_NUMBER);\n return {\n tool: 'read',\n args: { path: requestedPath, startLine: nextStart, endLine: nextEnd },\n hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,\n };\n}\n\n/**\n * The published metadata plus the bytes this call read. `content` and\n * `mediaData` exist only between `readOnePath` and the content blocks `run`\n * builds from them — they are stripped before the structured half is returned,\n * which is why they are not in `ReadPerPathValue`.\n */\ntype PerPathReadValue = ReadPerPathValue & {\n content?: string;\n mediaData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n}\n\ninterface BudgetItem {\n path: string;\n skip?: FsError;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n): Promise<BudgetItem[]> {\n const indexed = filePaths.map((path, index) => ({ path, index }));\n const { results } = await processInParallel(\n indexed,\n async ({ path, index }): Promise<BatchFileInfo | undefined> => {\n try {\n const out = await ctx.fs.stat(path);\n return { index, size: Math.min(out.stats.size, maxSize) };\n } catch (err: unknown) {\n ctx.log('debug', `collectFileBudget: stat failed for \"${path}\": ${String(err)}`, 'read');\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const byIndex = new Map<number, BatchFileInfo>();\n for (const { value: item } of results) {\n if (item) byIndex.set(item.index, item);\n }\n\n let total = 0;\n return filePaths.map((path, i): BudgetItem => {\n const info = byIndex.get(i);\n // A failed stat is not skipped, so its read surfaces the\n // real error, not a misleading TOO_LARGE.\n if (info === undefined) return { path };\n // Skip this file only; a later, smaller file that still fits is read.\n if (total + info.size > maxTotalSize) {\n return {\n path,\n skip: new FsError(\n ErrorCode.TOO_LARGE,\n `Skipped: this file alone would push the batch past maxTotalSize (${String(maxTotalSize)} bytes). Read it on its own with path instead of paths.`,\n path,\n ),\n };\n }\n total += info.size;\n return { path };\n });\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; requestedPath: string },\n): PerPathReadValue {\n const mimeInfo = detectMimeFromContent(result.path, result.content);\n const continuation =\n result.hasMoreLines && result.readMode !== 'tail'\n ? buildReadContinuation(result, options.requestedPath)\n : undefined;\n const contentHash = options.includeHash\n ? createHash('sha256').update(result.content, 'utf-8').digest('hex')\n : undefined;\n\n return {\n content: result.content,\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n ...(continuation ? { continuation } : {}),\n ...(result.totalLines !== undefined ? { totalLines: result.totalLines } : {}),\n ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),\n ...(result.hasMoreLines ? { hasMoreLines: true } : {}),\n ...(result.head !== undefined ? { head: result.head } : {}),\n ...(result.tail !== undefined ? { tail: result.tail } : {}),\n ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),\n ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),\n ...(contentHash !== undefined ? { contentHash } : {}),\n resourceUri: buildFileResourceUri(result.path),\n modified: result.modified,\n };\n}\n\n/**\n * The two facts the model cannot act on without: that lines were dropped, and\n * the exact args to get the next chunk. Both used to live only in the structured\n * half, which no longer reaches the model. Each line is `//` prefixed and set\n * off by a blank line so it cannot be read as file bytes — do not drop either\n * guard.\n */\nfunction readTrailer(v: PerPathReadValue): string[] {\n const lines: string[] = [];\n if (v.continuation) {\n lines.push(\n `// truncated: ${v.continuation.hint} Continue: read ${JSON.stringify(v.continuation.args)}`,\n );\n } else if (v.hasMoreLines && v.linesRead !== undefined) {\n // A tail read gets no continuation — there are no args that read *backwards*\n // — so say what was shown rather than leaving the truncation silent.\n lines.push(`// truncated: showing last ${String(v.linesRead)} lines`);\n }\n if (v.contentHash !== undefined) lines.push(`// sha256: ${v.contentHash}`);\n return lines;\n}\n\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n // Image/audio full read: return a media content block instead of throwing\n // INVALID_INPUT (\"Binary file detected.\"). Line-range reads are\n // text-oriented and stay rejected. `readRaw` enforces the same size cap as\n // the text path (getMaxTextFileSize), so a too-large image surfaces TOO_LARGE\n // rather than blowing memory. svg carries kind:'image' but is XML text —\n // readRaw.isBinary is false for it, so it falls through to the text path.\n const isRangeRead =\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined;\n if (!isRangeRead) {\n const mime = detectMimeType(filePath);\n if (mime.kind === 'image' || mime.kind === 'audio') {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n if (raw.isBinary) {\n return {\n content: `[binary ${mime.kind} content: ${String(raw.content.length)} bytes; returned as a ${mime.kind} content block]`,\n mimeType: raw.mimeType,\n kind: mime.kind,\n mediaData: raw.content.toString('base64'),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n // The read re-validates and re-stats: the budget pass's stat is only a\n // size estimate, never a substitute for the guarded open.\n const result = await ctx.fs.readFile(filePath, spec);\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote. `result.path` is the resolved absolute one — on Windows that\n // is a backslash-doubling JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ = defineTool<typeof ReadFileInputSchema, BatchResult<ReadPerPathValue>>({\n name: 'read',\n title: 'Read File',\n description:\n 'Read text files, like cat: whole, or one slice via head, tail, or startLine/endLine. ' +\n 'Images and audio return as media; other binary files are rejected.',\n input: ReadFileInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.NOT_FILE,\n progress: (args) => {\n const isBatch = args.paths !== undefined;\n const name = isBatch ? `${String(args.paths?.length ?? 0)} files` : basename(args.path ?? '');\n if (isBatch) {\n return { label: READ_TOOL_LABEL, subject: name };\n }\n let scope: string | undefined;\n if (args.startLine !== undefined) {\n const end = args.endLine ?? '...';\n scope = `${args.startLine}-${String(end)}`;\n } else if (args.head !== undefined) {\n scope = `head ${args.head}`;\n } else if (args.tail !== undefined) {\n scope = `tail ${args.tail}`;\n }\n return { label: READ_TOOL_LABEL, subject: name, ...(scope ? { scope } : {}) };\n },\n accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n const items: BudgetItem[] =\n args.paths !== undefined\n ? await collectFileBudget(args.paths, READ_MANY_MAX_TOTAL_BYTES, getMaxTextFileSize(), ctx)\n : [{ path: args.path ?? '' }];\n const { results: ordered, summary } = await runOverPaths(\n items,\n ctx,\n ErrorCode.NOT_FILE,\n ({ path, skip }) => {\n if (skip) throw skip;\n return readOnePath(path, args, ctx);\n },\n );\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\n // Image/audio full read: emit the media content block alongside the\n // structured value. The base64 lives in v.mediaData (set in readOnePath).\n if (v.mediaData && v.mimeType && (v.kind === 'image' || v.kind === 'audio')) {\n resources.push(\n v.kind === 'image'\n ? { type: 'image', data: v.mediaData, mimeType: v.mimeType }\n : { type: 'audio', data: v.mediaData, mimeType: v.mimeType },\n );\n continue;\n }\n if (!v.resourceUri || !v.content) continue;\n // `result.path` is the path as *requested*; `v.resourceUri` was built from\n // the *validated* one. Rebuilding from the request would emit a second URI\n // for the same file whenever the two differ in case — subscribe by one and\n // unsubscribe by the other and the watcher never goes away.\n resources.push(\n buildFileResourceLinkFor(\n v.resourceUri,\n basename(result.path),\n v.mimeType ?? 'application/octet-stream',\n Buffer.byteLength(v.content, 'utf8'),\n v.modified,\n ),\n );\n }\n\n const [firstOrdered] = ordered;\n const body = (v: PerPathReadValue): string => {\n const content = v.content ?? 'read failed';\n const trailer = readTrailer(v);\n if (trailer.length === 0) return content;\n // Exactly one blank line between the bytes and the trailer, whether or not\n // the file ended in a newline.\n return `${content}${content.endsWith('\\n') ? '\\n' : '\\n\\n'}${trailer.join('\\n')}`;\n };\n const text =\n ordered.length === 1 && firstOrdered !== undefined\n ? 'error' in firstOrdered\n ? firstOrdered.error.message\n : body(firstOrdered.value)\n : ordered\n .map((r) => {\n const header = `// ${r.path}`;\n if ('value' in r) return `${header}\\n${body(r.value)}`;\n return `${header}\\n// Error: ${r.error.message}`;\n })\n .join('\\n\\n');\n\n // The bytes ship once. `text` above already carries every file's content\n // verbatim (and image/audio bytes ride the media content block), so\n // repeating them under `results[].value` doubled both the wire payload and\n // the model's token cost for every read. The structured half keeps the\n // metadata a client cannot recover from the text: paths, line counts,\n // hashes, continuations, resourceUri.\n const structuredResults = ordered.map((result) => {\n if ('error' in result) return result;\n const { content: _content, mediaData: _mediaData, ...value } = result.value;\n return { ...result, value };\n });\n\n return {\n structured: { results: structuredResults, summary },\n text,\n isError: isTotalFailure(summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n // Media cannot be sliced, so head/tail is no remedy for it.\n oversizeRemedy: (result) =>\n result.resources?.some((b) => b.type === 'image' || b.type === 'audio')\n ? 'This media file is too large to return over the stdio transport; connect over HTTP, or raise it as a smaller file.'\n : 'Read a slice with head, tail, or startLine/endLine.',\n});\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { createHash } from 'node:crypto';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.ts';\nimport {\n detectMimeFromContent,\n detectMimeType,\n type FileKind,\n isKnownBinaryExtension,\n} from '../core/mime.ts';\nimport {\n BINARY_FILE_MESSAGE,\n isBinaryRefusal,\n type ReadFileResult,\n type ReadSpec,\n} from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n mapSingleOrBatchPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.ts';\nimport {\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n READ_MANY_MAX_TOTAL_BYTES,\n} from '../core/util.ts';\nimport type { BatchResult } from './batch.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\n/**\n * `z.int32()`'s own ceiling on startLine/endLine, named so a continuation\n * never asks for more. Not restated as `.max()`: that reports it twice.\n */\nconst MAX_LINE_NUMBER = 2_147_483_647;\n\nconst rangeField = (description: string, count = false) => {\n const field = z.int32().min(1, { message: 'Min: 1' });\n return (count ? field.max(100000, { message: 'Max: 100,000' }) : field)\n .optional()\n .describe(description);\n};\n\nconst readRangeFields = {\n head: rangeField('Return first N lines', true),\n tail: rangeField('Return last N lines', true),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed); requires startLine'),\n};\n\n/** A slice read: only a full read returns media or a binary resource. */\nfunction hasLineRange(args: {\n head?: number | undefined;\n tail?: number | undefined;\n startLine?: number | undefined;\n endLine?: number | undefined;\n}): boolean {\n return (\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined\n );\n}\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n binary: defaultFalseBoolean(\n 'Return a binary file that is not an image or audio whole, as a base64 embedded resource. Full reads only.',\n ),\n ...readRangeFields,\n}).superRefine((value, ctx) => {\n validateReadRange(\n {\n head: value.head,\n tail: value.tail,\n startLine: value.startLine,\n endLine: value.endLine,\n },\n ctx,\n );\n if (value.binary && hasLineRange(value)) {\n ctx.addIssue({\n code: 'custom',\n path: ['binary'],\n message:\n \"Cannot use 'binary' with 'head'/'tail'/'startLine'/'endLine'. A binary file is read whole.\",\n input: value,\n });\n }\n});\n\ninterface ReadContinuation {\n tool: 'read';\n args: { path: string; startLine: number; endLine: number };\n hint: string;\n}\n\n// File bytes ride content blocks, never the structured metadata.\ninterface ReadPerPathValue {\n mimeType?: string;\n kind?: FileKind;\n resourceUri?: string;\n /** Bytes in the file; set when the bytes ride a media or resource block. */\n size?: number;\n /** ISO-8601 mtime at read time; also rides the resource_link. */\n modified?: string;\n continuation?: ReadContinuation;\n totalLines?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n contentHash?: string;\n}\n\ntype ReadFileInput = z.infer<typeof ReadFileInputSchema>;\n\nconst READ_TOOL_LABEL = 'Read';\n\nfunction buildReadSpec(args: ReadFileInput, signal?: AbortSignal): ReadSpec {\n const signalPart = signal ? { signal } : {};\n const { head, tail, startLine, endLine } = args;\n\n if (head !== undefined) return { kind: 'head', lines: head, ...signalPart };\n if (tail !== undefined) return { kind: 'tail', lines: tail, ...signalPart };\n if (startLine !== undefined || endLine !== undefined) {\n return {\n kind: 'range',\n start: startLine ?? 1,\n ...(endLine !== undefined ? { end: endLine } : {}),\n ...signalPart,\n };\n }\n return { kind: 'full', ...signalPart };\n}\n\n// No `totalLines`: only `readFull` counts them and a full read never leaves\n// more behind, so a continuation cannot know the total without a second pass.\nfunction buildReadContinuation(\n result: ReadFileResult,\n requestedPath: string,\n): ReadContinuation | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\n // Args the schema would reject are no continuation; clamp the end into it.\n if (nextStart > MAX_LINE_NUMBER) return undefined;\n let chunkSize: number;\n if (result.head !== undefined) {\n chunkSize = result.head;\n } else if (result.startLine !== undefined && result.endLine !== undefined) {\n chunkSize = result.endLine - result.startLine + 1;\n } else {\n chunkSize = DEFAULT_CONTINUATION_CHUNK_SIZE;\n }\n const nextEnd = Math.min(nextStart + chunkSize - 1, MAX_LINE_NUMBER);\n return {\n tool: 'read',\n args: { path: requestedPath, startLine: nextStart, endLine: nextEnd },\n hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,\n };\n}\n\n/**\n * The published metadata plus the bytes this call read. `content`, `mediaData`\n * and `blobData` exist only between `readOnePath` and the content blocks `run`\n * builds from them — they are stripped before the structured half is returned,\n * which is why they are not in `ReadPerPathValue`.\n */\ntype PerPathReadValue = ReadPerPathValue & {\n content?: string;\n fileSize?: number;\n mediaData?: string;\n blobData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n}\n\ninterface BudgetItem {\n path: string;\n skip?: FsError;\n}\n\ninterface BudgetMode {\n fullRead: boolean;\n binary: boolean;\n}\n\n/**\n * What a file costs the batch: one whose bytes ship as base64 costs that size.\n * Only a full read ships base64; a slice of an svg is text.\n */\nfunction budgetBytes(path: string, size: number, { fullRead, binary }: BudgetMode): number {\n if (!fullRead) return size;\n const { kind } = detectMimeType(path);\n const base64 = kind === 'image' || kind === 'audio' || (binary && isKnownBinaryExtension(path));\n return base64 ? 4 * Math.ceil(size / 3) : size;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n mode: BudgetMode,\n): Promise<BudgetItem[]> {\n const indexed = filePaths.map((path, index) => ({ path, index }));\n const { results } = await processInParallel(\n indexed,\n async ({ path, index }): Promise<BatchFileInfo | undefined> => {\n try {\n const out = await ctx.fs.stat(path);\n return { index, size: budgetBytes(path, Math.min(out.stats.size, maxSize), mode) };\n } catch (err: unknown) {\n ctx.log('debug', `collectFileBudget: stat failed for \"${path}\": ${String(err)}`, 'read');\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const byIndex = new Map<number, BatchFileInfo>();\n for (const { value: item } of results) {\n if (item) byIndex.set(item.index, item);\n }\n\n let total = 0;\n return filePaths.map((path, i): BudgetItem => {\n const info = byIndex.get(i);\n // A failed stat is not skipped, so its read surfaces the\n // real error, not a misleading TOO_LARGE.\n if (info === undefined) return { path };\n // Skip this file only; a later, smaller file that still fits is read.\n if (total + info.size > maxTotalSize) {\n return {\n path,\n skip: new FsError(\n ErrorCode.TOO_LARGE,\n `Skipped: this file alone would push the batch past maxTotalSize (${String(maxTotalSize)} bytes). Read it on its own with path instead of paths.`,\n path,\n ),\n };\n }\n total += info.size;\n return { path };\n });\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; requestedPath: string },\n): PerPathReadValue {\n const mimeInfo = detectMimeFromContent(result.path, result.content);\n const continuation =\n result.hasMoreLines && result.readMode !== 'tail'\n ? buildReadContinuation(result, options.requestedPath)\n : undefined;\n const contentHash = options.includeHash\n ? createHash('sha256').update(result.content, 'utf-8').digest('hex')\n : undefined;\n\n const canLink = result.fileSize === undefined || result.fileSize <= getMaxTextFileSize();\n\n return {\n content: result.content,\n ...(result.fileSize !== undefined ? { fileSize: result.fileSize } : {}),\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n ...(continuation ? { continuation } : {}),\n ...(result.totalLines !== undefined ? { totalLines: result.totalLines } : {}),\n ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),\n ...(result.hasMoreLines ? { hasMoreLines: true } : {}),\n ...(result.head !== undefined ? { head: result.head } : {}),\n ...(result.tail !== undefined ? { tail: result.tail } : {}),\n ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),\n ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),\n ...(contentHash !== undefined ? { contentHash } : {}),\n ...(canLink ? { resourceUri: buildFileResourceUri(result.path) } : {}),\n modified: result.modified,\n };\n}\n\n/**\n * The two facts the model cannot act on without: that lines were dropped, and\n * the exact args to get the next chunk. Both used to live only in the structured\n * half, which no longer reaches the model. Each line is `//` prefixed and set\n * off by a blank line so it cannot be read as file bytes — do not drop either\n * guard.\n */\nfunction readTrailer(v: PerPathReadValue): string[] {\n const lines: string[] = [];\n if (v.continuation) {\n lines.push(\n `// truncated: ${v.continuation.hint} Continue: read ${JSON.stringify(v.continuation.args)}`,\n );\n } else if (v.hasMoreLines && v.linesRead !== undefined) {\n // A tail read gets no continuation — there are no args that read *backwards*\n // — so say what was shown rather than leaving the truncation silent.\n lines.push(`// truncated: showing last ${String(v.linesRead)} lines`);\n }\n if (v.contentHash !== undefined) lines.push(`// sha256: ${v.contentHash}`);\n return lines;\n}\n\n/**\n * `binary: true` after the text path refused the file as binary. readRaw\n * re-validates the path (roots, denylist) and enforces the same size cap.\n * A file refused by its extension can still probe as text: it ships as the\n * extension says, octet-stream.\n */\nasync function readBinaryResource(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n const asText = raw.kind === 'text';\n const kind: FileKind = asText ? 'binary' : raw.kind;\n const mimeType = asText ? 'application/octet-stream' : raw.mimeType;\n const size = raw.content.length;\n return {\n content: `[binary ${kind} content: ${String(size)} bytes (${mimeType}); returned as an embedded resource block]`,\n mimeType,\n kind,\n size,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n blobData: raw.content.toString('base64'),\n ...(args.includeHash\n ? { contentHash: createHash('sha256').update(raw.content).digest('hex') }\n : {}),\n };\n}\n\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n // Image/audio full read: return a media content block instead of throwing\n // INVALID_INPUT (\"Binary file detected.\"). Line-range reads are\n // text-oriented and stay rejected. `readRaw` enforces the same size cap as\n // the text path (getMaxTextFileSize), so a too-large image surfaces TOO_LARGE\n // rather than blowing memory. svg is kind 'image' in EXT_MAP, so readRaw\n // reports it binary and it returns as an image block.\n const isRangeRead = hasLineRange(args);\n if (!isRangeRead) {\n const mime = detectMimeType(filePath);\n if (mime.kind === 'image' || mime.kind === 'audio') {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n if (raw.isBinary) {\n return {\n content: `[binary ${mime.kind} content: ${String(raw.content.length)} bytes; returned as a ${mime.kind} content block]`,\n mimeType: raw.mimeType,\n kind: mime.kind,\n size: raw.content.length,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n mediaData: raw.content.toString('base64'),\n ...(args.includeHash\n ? { contentHash: createHash('sha256').update(raw.content).digest('hex') }\n : {}),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n // The read re-validates and re-stats: the budget pass's stat is only a\n // size estimate, never a substitute for the guarded open.\n let result: ReadFileResult;\n try {\n result = await ctx.fs.readFile(filePath, spec);\n } catch (error: unknown) {\n if (!isBinaryRefusal(error)) throw error;\n // The schema refuses binary with a range, so this is always a full read.\n if (args.binary) return await readBinaryResource(filePath, args, ctx);\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n isRangeRead\n ? `${BINARY_FILE_MESSAGE} It has no lines; read it whole with binary: true to get it as a base64 embedded resource.`\n : `${BINARY_FILE_MESSAGE} Pass binary: true to get it as a base64 embedded resource.`,\n filePath,\n error,\n );\n }\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote, or the root-resolved one a relative path was rewritten to.\n // `result.path` is the real path — on Windows that is a backslash-doubling\n // JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ = defineTool<typeof ReadFileInputSchema, BatchResult<ReadPerPathValue>>({\n name: 'read',\n title: 'Read File',\n description:\n 'Read text files, like cat: whole, or one slice via head, tail, or startLine/endLine. ' +\n 'Images and audio return as media; pass binary: true to get any other binary file whole as a base64 embedded resource.',\n input: ReadFileInputSchema,\n readOnlyHint: true,\n deadline: true,\n defaultErrorCode: ErrorCode.NOT_FILE,\n progress: (args) => {\n const isBatch = args.paths !== undefined;\n const name = isBatch ? `${String(args.paths?.length ?? 0)} files` : basename(args.path ?? '');\n if (isBatch) {\n return { label: READ_TOOL_LABEL, subject: name };\n }\n let scope: string | undefined;\n if (args.startLine !== undefined) {\n const end = args.endLine ?? '...';\n scope = `${args.startLine}-${String(end)}`;\n } else if (args.head !== undefined) {\n scope = `head ${args.head}`;\n } else if (args.tail !== undefined) {\n scope = `tail ${args.tail}`;\n }\n return { label: READ_TOOL_LABEL, subject: name, ...(scope ? { scope } : {}) };\n },\n mapPaths: mapSingleOrBatchPaths,\n run: async (args, ctx) => {\n const items: BudgetItem[] =\n args.paths !== undefined\n ? await collectFileBudget(\n args.paths,\n READ_MANY_MAX_TOTAL_BYTES,\n getMaxTextFileSize(),\n ctx,\n { fullRead: !hasLineRange(args), binary: args.binary },\n )\n : [{ path: args.path ?? '' }];\n const { results: ordered, summary } = await runOverPaths(\n items,\n ctx,\n ErrorCode.NOT_FILE,\n ({ path, skip }) => {\n if (skip) throw skip;\n return readOnePath(path, args, ctx);\n },\n );\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\n if (v.blobData !== undefined && v.resourceUri !== undefined && v.mimeType !== undefined) {\n resources.push({\n type: 'resource',\n resource: { uri: v.resourceUri, mimeType: v.mimeType, blob: v.blobData },\n });\n continue;\n }\n // Image/audio full read: emit the media content block alongside the\n // structured value. The base64 lives in v.mediaData (set in readOnePath).\n if (v.mediaData && v.mimeType && (v.kind === 'image' || v.kind === 'audio')) {\n resources.push(\n v.kind === 'image'\n ? { type: 'image', data: v.mediaData, mimeType: v.mimeType }\n : { type: 'audio', data: v.mediaData, mimeType: v.mimeType },\n );\n continue;\n }\n if (!v.resourceUri || v.content === undefined) continue;\n // `result.path` is the path as *requested*; `v.resourceUri` was built from\n // the *validated* one. Rebuilding from the request would emit a second URI\n // for the same file whenever the two differ in case — subscribe by one and\n // unsubscribe by the other and the watcher never goes away.\n resources.push(\n buildFileResourceLinkFor(\n v.resourceUri,\n basename(result.path),\n v.mimeType ?? 'application/octet-stream',\n v.fileSize ?? Buffer.byteLength(v.content, 'utf8'),\n v.modified,\n ),\n );\n }\n\n const [firstOrdered] = ordered;\n const body = (v: PerPathReadValue): string => {\n const content = v.content ?? 'read failed';\n const trailer = readTrailer(v);\n if (trailer.length === 0) return content;\n // Exactly one blank line between the bytes and the trailer, whether or not\n // the file ended in a newline.\n return `${content}${content.endsWith('\\n') ? '\\n' : '\\n\\n'}${trailer.join('\\n')}`;\n };\n const text =\n ordered.length === 1 && firstOrdered !== undefined\n ? 'error' in firstOrdered\n ? firstOrdered.error.message\n : body(firstOrdered.value)\n : ordered\n .map((r) => {\n const header = `// ${r.path}`;\n if ('value' in r) return `${header}\\n${body(r.value)}`;\n return `${header}\\n// Error: ${r.error.message}`;\n })\n .join('\\n\\n');\n\n // The bytes ship once. `text` above already carries every file's content\n // verbatim (and image/audio bytes ride the media content block), so\n // repeating them under `results[].value` doubled both the wire payload and\n // the model's token cost for every read. The structured half keeps the\n // metadata a client cannot recover from the text: paths, line counts,\n // hashes, continuations, resourceUri.\n const structuredResults = ordered.map((result) => {\n if ('error' in result) return result;\n const {\n content: _content,\n fileSize: _fileSize,\n mediaData: _mediaData,\n blobData: _blobData,\n ...value\n } = result.value;\n return { ...result, value };\n });\n\n return {\n structured: { results: structuredResults, summary },\n text,\n isError: isTotalFailure(summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n // Media and binary resources cannot be sliced, so head/tail is no remedy.\n oversizeRemedy: (result) => {\n const types = new Set(result.resources?.map((b) => b.type));\n if (types.has('image') || types.has('audio')) {\n return 'This media file is too large to return over the stdio transport; connect over HTTP, or raise it as a smaller file.';\n }\n if (types.has('resource')) {\n return 'This binary file is too large to return over the stdio transport; connect over HTTP.';\n }\n return 'Read a slice with head, tail, or startLine/endLine.';\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-text.d.ts","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replace-text.d.ts","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"AAqlBA,eAAO,MAAM,YAAY,mCA6FvB,CAAC"}
|