@j0hanz/filesystem-mcp 2.1.5 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -13
- package/dist/cli.js.map +1 -1
- package/dist/core/diff.d.ts +6 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +21 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/errors.d.ts +0 -20
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -60
- package/dist/core/errors.js.map +1 -1
- package/dist/core/file-uri.d.ts +18 -2
- package/dist/core/file-uri.d.ts.map +1 -1
- package/dist/core/file-uri.js +34 -6
- package/dist/core/file-uri.js.map +1 -1
- package/dist/core/fs.d.ts +1 -2
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +3 -22
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +1 -6
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +0 -9
- package/dist/core/glob.js.map +1 -1
- package/dist/core/input-required.d.ts +2 -4
- package/dist/core/input-required.d.ts.map +1 -1
- package/dist/core/input-required.js +3 -4
- package/dist/core/input-required.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +1 -6
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path.d.ts +4 -8
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +13 -26
- package/dist/core/path.js.map +1 -1
- package/dist/core/primitives.d.ts +8 -2
- package/dist/core/primitives.d.ts.map +1 -1
- package/dist/core/primitives.js +10 -2
- package/dist/core/primitives.js.map +1 -1
- package/dist/core/read.d.ts +0 -15
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +12 -41
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts +1 -16
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +7 -41
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +39 -3
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +72 -17
- package/dist/core/search.js.map +1 -1
- package/dist/core/sensitive.d.ts.map +1 -1
- package/dist/core/sensitive.js +7 -15
- package/dist/core/sensitive.js.map +1 -1
- package/dist/core/store.d.ts +0 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +0 -1
- package/dist/core/store.js.map +1 -1
- package/dist/index.js +1 -8
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +13 -28
- package/dist/prompts.js.map +1 -1
- package/dist/tools/batch.d.ts +5 -78
- package/dist/tools/batch.d.ts.map +1 -1
- package/dist/tools/batch.js +6 -115
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +8 -18
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +1 -4
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +1 -22
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete-file.d.ts.map +1 -1
- package/dist/tools/delete-file.js +6 -6
- package/dist/tools/delete-file.js.map +1 -1
- package/dist/tools/diff.d.ts.map +1 -1
- package/dist/tools/diff.js +3 -10
- package/dist/tools/diff.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +35 -72
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list.js +2 -1
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +162 -116
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.d.ts.map +1 -1
- package/dist/tools/patch.js +5 -23
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +20 -21
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-in-files.d.ts.map +1 -1
- package/dist/tools/replace-in-files.js +33 -51
- package/dist/tools/replace-in-files.js.map +1 -1
- package/dist/tools/search-content.d.ts.map +1 -1
- package/dist/tools/search-content.js +10 -31
- package/dist/tools/search-content.js.map +1 -1
- package/dist/tools/search-files.d.ts.map +1 -1
- package/dist/tools/search-files.js +1 -2
- package/dist/tools/search-files.js.map +1 -1
- package/dist/tools/stat.d.ts.map +1 -1
- package/dist/tools/stat.js +4 -3
- package/dist/tools/stat.js.map +1 -1
- package/dist/transport/http-policy.js +1 -1
- package/dist/transport/http-policy.js.map +1 -1
- package/package.json +1 -1
package/dist/core/read.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAwC,OAAO,EAAa,MAAM,aAAa,CAAC;AAqEvF,MAAM,MAAM,QAAQ,GAChB;
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAwC,OAAO,EAAa,MAAM,aAAa,CAAC;AAqEvF,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAEzE,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,KAAK,cAAc,GACf,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACnC,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAClD,CAAC,cAAc,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAQtE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA+BD,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAkB5D;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAMT;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,MAI5C,CAAC;AA8ZF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAIpE;AAED,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,OAAO,CAAC,cAAc,CAAC,CAEzB"}
|
package/dist/core/read.js
CHANGED
|
@@ -118,14 +118,8 @@ async function isProbablyBinary(filePath, existingHandle, signal) {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
function buildBaseOptions(spec) {
|
|
121
|
-
if (spec.maxSize !== undefined) {
|
|
122
|
-
assertPositiveIntegerOption('maxSize', spec.maxSize, 'maxSize must be at least 1');
|
|
123
|
-
}
|
|
124
|
-
const maxTextFileSize = getMaxTextFileSize();
|
|
125
121
|
return {
|
|
126
|
-
|
|
127
|
-
maxSize: Math.min(spec.maxSize ?? maxTextFileSize, maxTextFileSize),
|
|
128
|
-
skipBinary: spec.skipBinary ?? false,
|
|
122
|
+
maxSize: getMaxTextFileSize(),
|
|
129
123
|
...(spec.signal ? { signal: spec.signal } : {}),
|
|
130
124
|
};
|
|
131
125
|
}
|
|
@@ -162,15 +156,6 @@ export function normalizeSpec(spec) {
|
|
|
162
156
|
}
|
|
163
157
|
}
|
|
164
158
|
}
|
|
165
|
-
function buildReadContentOptions(normalized) {
|
|
166
|
-
const result = {
|
|
167
|
-
encoding: normalized.encoding,
|
|
168
|
-
maxSize: normalized.maxSize,
|
|
169
|
-
};
|
|
170
|
-
if (normalized.signal)
|
|
171
|
-
result.signal = normalized.signal;
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
159
|
export function createTooLargeError(bytesRead, maxSize, requestedPath) {
|
|
175
160
|
return new FsError(ErrorCode.TOO_LARGE, `File exceeds size limit (${bytesRead} > ${maxSize} bytes)`, requestedPath);
|
|
176
161
|
}
|
|
@@ -248,7 +233,7 @@ async function* readLinesBounded(handle, options, filePath, startLine) {
|
|
|
248
233
|
emitClose: false,
|
|
249
234
|
...(options.signal ? { signal: options.signal } : {}),
|
|
250
235
|
});
|
|
251
|
-
const decoder = new StringDecoder(
|
|
236
|
+
const decoder = new StringDecoder('utf-8');
|
|
252
237
|
let pending = '';
|
|
253
238
|
let pendingBytes = 0;
|
|
254
239
|
let lineNumber = 0;
|
|
@@ -314,10 +299,9 @@ async function readRangeContent(handle, startLine, endLine, options, filePath) {
|
|
|
314
299
|
const lines = [];
|
|
315
300
|
let lineNumber = startLine - 1;
|
|
316
301
|
let estimatedBytes = 0;
|
|
317
|
-
const newlineBytes = Buffer.byteLength('\n',
|
|
302
|
+
const newlineBytes = Buffer.byteLength('\n', 'utf-8');
|
|
318
303
|
const stopAt = endLine ?? Number.POSITIVE_INFINITY;
|
|
319
304
|
let hasMoreLines = false;
|
|
320
|
-
let stoppedByLimit = false;
|
|
321
305
|
// Byte-bounded: an over-long line throws TOO_LARGE while still a partial
|
|
322
306
|
// buffer, before it can be decoded into one huge string.
|
|
323
307
|
const iterator = readLinesBounded(handle, options, filePath, startLine)[Symbol.asyncIterator]();
|
|
@@ -333,9 +317,8 @@ async function readRangeContent(handle, startLine, endLine, options, filePath) {
|
|
|
333
317
|
break;
|
|
334
318
|
}
|
|
335
319
|
lines.push(line);
|
|
336
|
-
estimatedBytes += Buffer.byteLength(line,
|
|
320
|
+
estimatedBytes += Buffer.byteLength(line, 'utf-8') + newlineBytes;
|
|
337
321
|
if (estimatedBytes > options.maxSize) {
|
|
338
|
-
stoppedByLimit = true;
|
|
339
322
|
hasMoreLines = await peekHasMore(iterator);
|
|
340
323
|
break;
|
|
341
324
|
}
|
|
@@ -350,7 +333,6 @@ async function readRangeContent(handle, startLine, endLine, options, filePath) {
|
|
|
350
333
|
}
|
|
351
334
|
return {
|
|
352
335
|
content: lines.join('\n'),
|
|
353
|
-
truncated: stoppedByLimit || hasMoreLines,
|
|
354
336
|
linesRead: lines.length,
|
|
355
337
|
hasMoreLines,
|
|
356
338
|
};
|
|
@@ -362,12 +344,11 @@ async function readTailContent(handle, tail, options, filePath) {
|
|
|
362
344
|
if (fileSize === 0) {
|
|
363
345
|
return {
|
|
364
346
|
content: '',
|
|
365
|
-
truncated: false,
|
|
366
347
|
linesRead: 0,
|
|
367
348
|
hasMoreLines: false,
|
|
368
349
|
};
|
|
369
350
|
}
|
|
370
|
-
const encoding =
|
|
351
|
+
const encoding = 'utf-8';
|
|
371
352
|
// Accumulate raw bytes from the end: decoding a chunk ending mid-codepoint
|
|
372
353
|
// corrupts the trailing UTF-8 sequence into U+FFFD. 0x0A is single-byte and
|
|
373
354
|
// never part of a multibyte sequence, so count newlines on the raw buffer and
|
|
@@ -430,14 +411,13 @@ async function readTailContent(handle, tail, options, filePath) {
|
|
|
430
411
|
const content = lines.join('\n');
|
|
431
412
|
return {
|
|
432
413
|
content,
|
|
433
|
-
truncated: hasMoreLines,
|
|
434
414
|
linesRead: lines.length,
|
|
435
415
|
hasMoreLines,
|
|
436
416
|
};
|
|
437
417
|
}
|
|
438
|
-
async function readFullContent(handle,
|
|
418
|
+
async function readFullContent(handle, maxSize, requestedPath, signal) {
|
|
439
419
|
const buffer = await readFileBufferWithLimit(handle, maxSize, requestedPath, signal);
|
|
440
|
-
const content = buffer.toString(
|
|
420
|
+
const content = buffer.toString('utf-8');
|
|
441
421
|
return { content, totalLines: countLines(content) };
|
|
442
422
|
}
|
|
443
423
|
async function assertNotBinary(validPath, filePath, handle, normalized) {
|
|
@@ -453,12 +433,10 @@ function assertSizeWithinLimit(size, maxSize, filePath) {
|
|
|
453
433
|
throw new FsError(ErrorCode.TOO_LARGE, `File too large (${size} > ${maxSize} bytes). Use head to preview.`, filePath);
|
|
454
434
|
}
|
|
455
435
|
async function readHead(context, spec) {
|
|
456
|
-
const
|
|
457
|
-
const { content, truncated, linesRead, hasMoreLines } = await readRangeContent(context.handle, 1, spec.lines, contentOptions, context.filePath);
|
|
436
|
+
const { content, linesRead, hasMoreLines } = await readRangeContent(context.handle, 1, spec.lines, spec, context.filePath);
|
|
458
437
|
return {
|
|
459
438
|
path: context.validPath,
|
|
460
439
|
content,
|
|
461
|
-
truncated,
|
|
462
440
|
readMode: 'head',
|
|
463
441
|
head: spec.lines,
|
|
464
442
|
linesRead,
|
|
@@ -466,12 +444,10 @@ async function readHead(context, spec) {
|
|
|
466
444
|
};
|
|
467
445
|
}
|
|
468
446
|
async function readRange(context, spec) {
|
|
469
|
-
const
|
|
470
|
-
const { content, truncated, linesRead, hasMoreLines } = await readRangeContent(context.handle, spec.start, spec.end, contentOptions, context.filePath);
|
|
447
|
+
const { content, linesRead, hasMoreLines } = await readRangeContent(context.handle, spec.start, spec.end, spec, context.filePath);
|
|
471
448
|
return {
|
|
472
449
|
path: context.validPath,
|
|
473
450
|
content,
|
|
474
|
-
truncated,
|
|
475
451
|
readMode: 'range',
|
|
476
452
|
startLine: spec.start,
|
|
477
453
|
...(spec.end !== undefined ? { endLine: spec.end } : {}),
|
|
@@ -481,11 +457,10 @@ async function readRange(context, spec) {
|
|
|
481
457
|
}
|
|
482
458
|
async function readFull(context, spec) {
|
|
483
459
|
assertSizeWithinLimit(context.stats.size, spec.maxSize, context.filePath);
|
|
484
|
-
const { content, totalLines } = await readFullContent(context.handle, spec.
|
|
460
|
+
const { content, totalLines } = await readFullContent(context.handle, spec.maxSize, context.filePath, spec.signal);
|
|
485
461
|
return {
|
|
486
462
|
path: context.validPath,
|
|
487
463
|
content,
|
|
488
|
-
truncated: false,
|
|
489
464
|
totalLines,
|
|
490
465
|
readMode: 'full',
|
|
491
466
|
linesRead: totalLines,
|
|
@@ -493,12 +468,10 @@ async function readFull(context, spec) {
|
|
|
493
468
|
};
|
|
494
469
|
}
|
|
495
470
|
async function readTail(context, spec) {
|
|
496
|
-
const
|
|
497
|
-
const { content, truncated, linesRead, hasMoreLines } = await readTailContent(context.handle, spec.lines, contentOptions, context.validPath);
|
|
471
|
+
const { content, linesRead, hasMoreLines } = await readTailContent(context.handle, spec.lines, spec, context.validPath);
|
|
498
472
|
return {
|
|
499
473
|
path: context.validPath,
|
|
500
474
|
content,
|
|
501
|
-
truncated,
|
|
502
475
|
readMode: 'tail',
|
|
503
476
|
tail: spec.lines,
|
|
504
477
|
linesRead,
|
|
@@ -532,9 +505,7 @@ export async function readNormalized(filePath, validPath, stats, spec) {
|
|
|
532
505
|
spec.signal?.throwIfAborted();
|
|
533
506
|
assertFileStats(filePath, stats);
|
|
534
507
|
const handle = __addDisposableResource(env_2, await openReadableFileHandle(validPath, spec.signal), true);
|
|
535
|
-
|
|
536
|
-
await assertNotBinary(validPath, filePath, handle, spec);
|
|
537
|
-
}
|
|
508
|
+
await assertNotBinary(validPath, filePath, handle, spec);
|
|
538
509
|
spec.signal?.throwIfAborted();
|
|
539
510
|
return await readByMode({ handle, validPath, filePath, stats, spec });
|
|
540
511
|
}
|
package/dist/core/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"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","sourcesContent":["// File reading pipeline split out of fs.ts. fs.ts imports from here; never the reverse.\nimport type { Stats } from 'node:fs';\nimport { open as fsOpen } from 'node:fs/promises';\nimport type { FileHandle } from 'node:fs/promises';\nimport { StringDecoder } from 'node:string_decoder';\n\nimport { withAbort } from './concurrency.js';\nimport { ErrorCode, formatUnknownErrorMessage, FsError, isFsError } from './errors.js';\nimport { isBinarySample, isKnownBinaryExtension, MIME_SAMPLE_SIZE } from './mime.js';\nimport { Logger } from './observability.js';\nimport { getMaxTextFileSize } from './util.js';\n\nconst STREAM_CHUNK_SIZE = 64 * 1024;\n\nconst READ_ONLY_FILE_FLAG = 'r';\n\nfunction assertPositiveIntegerOption(name: string, value: unknown, message?: string): void {\n if (\n value === undefined ||\n (typeof value === 'number' && Number.isSafeInteger(value) && value >= 1)\n )\n return;\n throw new FsError(ErrorCode.INVALID_INPUT, message ?? `${name} must be a positive integer`);\n}\n\nasync function openReadableFileHandle(filePath: string, signal?: AbortSignal): Promise<FileHandle> {\n const handlePromise = fsOpen(filePath, READ_ONLY_FILE_FLAG);\n if (!signal) return handlePromise;\n try {\n return await withAbort(handlePromise, signal);\n } catch (error) {\n void handlePromise\n .then((handle) => {\n void handle.close().catch((closeErr: unknown) => {\n Logger.warn(\n `Failed to close file handle for ${filePath} after abort: ${formatUnknownErrorMessage(closeErr)}`,\n );\n });\n })\n .catch(() => {\n /* ignore open error */\n });\n throw error;\n }\n}\n\nasync function readProbe(handle: FileHandle, signal?: AbortSignal): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe(MIME_SAMPLE_SIZE);\n const { bytesRead } = await withAbort(handle.read(buffer, 0, MIME_SAMPLE_SIZE, 0), signal);\n\n if (bytesRead === 0) {\n return Buffer.alloc(0);\n }\n\n return buffer.subarray(0, bytesRead);\n}\n\nasync function isProbablyBinary(\n filePath: string,\n existingHandle?: FileHandle,\n signal?: AbortSignal,\n): Promise<boolean> {\n if (isKnownBinaryExtension(filePath)) {\n return true;\n }\n\n if (existingHandle) {\n const slice = await readProbe(existingHandle, signal);\n return isBinarySample(slice);\n }\n\n await using handle = await openReadableFileHandle(filePath, signal);\n const slice = await readProbe(handle, signal);\n return isBinarySample(slice);\n}\n\nexport type ReadSpec =\n | {\n kind: 'full';\n encoding?: BufferEncoding;\n maxSize?: number;\n skipBinary?: boolean;\n signal?: AbortSignal;\n }\n | {\n kind: 'head';\n lines: number;\n encoding?: BufferEncoding;\n maxSize?: number;\n skipBinary?: boolean;\n signal?: AbortSignal;\n }\n | {\n kind: 'tail';\n lines: number;\n encoding?: BufferEncoding;\n maxSize?: number;\n skipBinary?: boolean;\n signal?: AbortSignal;\n }\n | {\n kind: 'range';\n start: number;\n end?: number;\n encoding?: BufferEncoding;\n maxSize?: number;\n skipBinary?: boolean;\n signal?: AbortSignal;\n };\n\ninterface NormalizedBase {\n encoding: BufferEncoding;\n maxSize: number;\n skipBinary: boolean;\n signal?: AbortSignal;\n}\n\ntype NormalizedSpec =\n | (NormalizedBase & { kind: 'full' })\n | (NormalizedBase & { kind: 'head'; lines: number })\n | (NormalizedBase & { kind: 'tail'; lines: number })\n | (NormalizedBase & { kind: 'range'; start: number; end?: number });\n\ninterface ReadContentOptions {\n encoding: BufferEncoding;\n maxSize: number;\n signal?: AbortSignal;\n}\n\ninterface PartialReadResult {\n content: string;\n truncated: boolean;\n linesRead: number;\n hasMoreLines: boolean;\n}\n\nexport interface ReadFileResult {\n path: string;\n content: string;\n truncated: boolean;\n totalLines?: number;\n readMode: ReadSpec['kind'];\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n}\n\nfunction buildBaseOptions(spec: ReadSpec): NormalizedBase {\n if (spec.maxSize !== undefined) {\n assertPositiveIntegerOption('maxSize', spec.maxSize, 'maxSize must be at least 1');\n }\n const maxTextFileSize = getMaxTextFileSize();\n return {\n encoding: spec.encoding ?? 'utf-8',\n maxSize: Math.min(spec.maxSize ?? maxTextFileSize, maxTextFileSize),\n skipBinary: spec.skipBinary ?? false,\n ...(spec.signal ? { signal: spec.signal } : {}),\n };\n}\n\nfunction normalizeRangeSpec(\n spec: Extract<ReadSpec, { kind: 'range' }>,\n base: NormalizedBase,\n): NormalizedSpec {\n assertPositiveIntegerOption('start', spec.start, 'start must be at least 1');\n if (spec.end !== undefined) {\n assertPositiveIntegerOption('end', spec.end, 'end must be at least 1');\n if (spec.end < spec.start) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n 'end must be greater than or equal to start (default: 1)',\n );\n }\n }\n return {\n ...base,\n kind: 'range',\n start: spec.start,\n ...(spec.end !== undefined ? { end: spec.end } : {}),\n };\n}\n\nexport function normalizeSpec(spec: ReadSpec): NormalizedSpec {\n const base = buildBaseOptions(spec);\n spec.signal?.throwIfAborted();\n\n switch (spec.kind) {\n case 'head':\n case 'tail':\n assertPositiveIntegerOption('lines', spec.lines, 'lines must be at least 1');\n return { ...base, kind: spec.kind, lines: spec.lines };\n case 'range':\n return normalizeRangeSpec(spec, base);\n case 'full':\n return { ...base, kind: 'full' };\n default: {\n const _exhaustive: never = spec;\n return _exhaustive;\n }\n }\n}\n\nfunction buildReadContentOptions(normalized: NormalizedBase): ReadContentOptions {\n const result: ReadContentOptions = {\n encoding: normalized.encoding,\n maxSize: normalized.maxSize,\n };\n if (normalized.signal) result.signal = normalized.signal;\n return result;\n}\n\nexport function createTooLargeError(\n bytesRead: number,\n maxSize: number,\n requestedPath: string,\n): FsError {\n return new FsError(\n ErrorCode.TOO_LARGE,\n `File exceeds size limit (${bytesRead} > ${maxSize} bytes)`,\n requestedPath,\n );\n}\n\nexport async function readFileBufferWithLimit(\n handle: FileHandle,\n maxSize: number,\n requestedPath: string,\n signal?: AbortSignal,\n): Promise<Buffer> {\n const stream = handle.createReadStream({\n start: 0,\n highWaterMark: STREAM_CHUNK_SIZE,\n autoClose: false,\n emitClose: false,\n signal,\n });\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n\n try {\n for await (const chunk of stream) {\n const buffer = chunk as Buffer;\n totalSize += buffer.length;\n\n if (totalSize > maxSize) {\n stream.destroy();\n throw createTooLargeError(totalSize, maxSize, requestedPath);\n }\n\n chunks.push(buffer);\n }\n } finally {\n if (!stream.destroyed) {\n stream.on('error', (_err: unknown) => {\n /* suppress post-destroy error event */\n });\n stream.destroy();\n }\n }\n\n return Buffer.concat(chunks, totalSize);\n}\n\nexport const countLines = (content: string): number => {\n if (content.length === 0) return 0;\n const trimmed = content.endsWith('\\n') ? content.slice(0, -1) : content;\n return trimmed.split('\\n').length;\n};\n\nasync function peekHasMore(iterator: AsyncIterator<string>): Promise<boolean> {\n try {\n const { done } = await iterator.next();\n return !done;\n } catch (error) {\n // The peek only asks \"is there another line\", and the caller keeps nothing\n // it returns. An over-long line past the requested range still answers yes\n // — failing the whole read over a line outside it would reject e.g. lines\n // 1-2 of a file whose line 3 is one 50 KB blob.\n if (isFsError(error) && error.code === ErrorCode.TOO_LARGE) return true;\n throw error;\n }\n}\n\nconst LF = 0x0a;\n\nfunction stripCarriageReturn(line: string): string {\n return line.endsWith('\\r') ? line.slice(0, -1) : line;\n}\n\n/**\n * Line iterator bounded by bytes rather than by the decoded string, so a file\n * that is one enormous line cannot be materialized before the size check runs.\n * `handle.readLines` decodes the whole line first and can OOM on such a file.\n *\n * Yields lines from `startLine` onward, 1-indexed. Lines before `startLine` are\n * counted and discarded without accumulating, so an over-long line the caller\n * skipped past does not fail the read. Line endings match `readLines`: split on\n * `\\n`, with a preceding `\\r` stripped, so CRLF input decodes identically.\n */\nasync function* readLinesBounded(\n handle: FileHandle,\n options: ReadContentOptions,\n filePath: string,\n startLine: number,\n): AsyncGenerator<string, void, undefined> {\n const stream = handle.createReadStream({\n start: 0,\n highWaterMark: STREAM_CHUNK_SIZE,\n autoClose: false,\n emitClose: false,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n\n const decoder = new StringDecoder(options.encoding);\n let pending = '';\n let pendingBytes = 0;\n let lineNumber = 0;\n\n const tooLong = (bytes: number): FsError =>\n new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (single line ${bytes} > ${options.maxSize} bytes). Use a narrower range or head.`,\n filePath,\n );\n\n try {\n for await (const chunk of stream) {\n const buffer = chunk as Buffer;\n let offset = 0;\n\n // Search loop: each iteration finds the next LF and advances offset past\n // it. Written as while-with-assignment so the re-search is visible, rather\n // than buried in a for \"increment\" slot that re-runs indexOf.\n let nl = buffer.indexOf(LF, offset);\n while (nl !== -1) {\n const segment = buffer.subarray(offset, nl);\n const lineBytes = pendingBytes + segment.length;\n lineNumber++;\n // Decode even when skipping: the decoder carries multi-byte\n // continuation state into the first line the caller keeps.\n const decoded = decoder.write(segment);\n if (lineNumber >= startLine) {\n if (lineBytes > options.maxSize) throw tooLong(lineBytes);\n yield stripCarriageReturn(pending + decoded);\n }\n pending = '';\n pendingBytes = 0;\n offset = nl + 1;\n nl = buffer.indexOf(LF, offset);\n }\n\n const rest = buffer.subarray(offset);\n pendingBytes += rest.length;\n if (lineNumber + 1 < startLine) {\n decoder.write(rest); // still skipping; drop the text, keep decoder state\n } else {\n if (pendingBytes > options.maxSize) throw tooLong(pendingBytes);\n pending += decoder.write(rest);\n }\n }\n\n // Trailing line with no final newline. A file ending in `\\n` leaves\n // pendingBytes at 0 and emits nothing, matching readLines.\n if (pendingBytes > 0) {\n lineNumber++;\n if (lineNumber >= startLine) {\n if (pendingBytes > options.maxSize) throw tooLong(pendingBytes);\n yield pending + decoder.end();\n }\n }\n } finally {\n if (!stream.destroyed) {\n stream.on('error', (_err: unknown) => {\n /* suppress post-destroy error event */\n });\n stream.destroy();\n }\n }\n}\n\nasync function readRangeContent(\n handle: FileHandle,\n startLine: number,\n endLine: number | undefined,\n options: ReadContentOptions,\n filePath: string,\n): Promise<PartialReadResult> {\n options.signal?.throwIfAborted();\n\n const lines: string[] = [];\n let lineNumber = startLine - 1;\n let estimatedBytes = 0;\n const newlineBytes = Buffer.byteLength('\\n', options.encoding);\n const stopAt = endLine ?? Number.POSITIVE_INFINITY;\n\n let hasMoreLines = false;\n let stoppedByLimit = false;\n\n // Byte-bounded: an over-long line throws TOO_LARGE while still a partial\n // buffer, before it can be decoded into one huge string.\n const iterator = readLinesBounded(handle, options, filePath, startLine)[Symbol.asyncIterator]();\n\n try {\n for (;;) {\n const { value: line, done } = await iterator.next();\n if (done) {\n break;\n }\n lineNumber++;\n\n if (lineNumber > stopAt) {\n hasMoreLines = true;\n break;\n }\n\n lines.push(line);\n\n estimatedBytes += Buffer.byteLength(line, options.encoding) + newlineBytes;\n if (estimatedBytes > options.maxSize) {\n stoppedByLimit = true;\n hasMoreLines = await peekHasMore(iterator);\n break;\n }\n\n if (lineNumber === stopAt) {\n hasMoreLines = await peekHasMore(iterator);\n break;\n }\n }\n } finally {\n await iterator.return();\n }\n\n return {\n content: lines.join('\\n'),\n truncated: stoppedByLimit || hasMoreLines,\n linesRead: lines.length,\n hasMoreLines,\n };\n}\n\nasync function readTailContent(\n handle: FileHandle,\n tail: number,\n options: ReadContentOptions,\n filePath: string,\n): Promise<PartialReadResult> {\n options.signal?.throwIfAborted();\n\n const stats = await handle.stat();\n const fileSize = stats.size;\n if (fileSize === 0) {\n return {\n content: '',\n truncated: false,\n linesRead: 0,\n hasMoreLines: false,\n };\n }\n\n const encoding = options.encoding;\n // Accumulate raw bytes from the end: decoding a chunk ending mid-codepoint\n // corrupts the trailing UTF-8 sequence into U+FFFD. 0x0A is single-byte and\n // never part of a multibyte sequence, so count newlines on the raw buffer and\n // decode the whole bounded buffer once at the end.\n let position = fileSize;\n const chunks: Buffer[] = [];\n let totalLen = 0;\n let newlines = 0;\n let stoppedByLimit = false;\n\n while (position > 0) {\n options.signal?.throwIfAborted();\n const chunkSize = Math.min(position, STREAM_CHUNK_SIZE);\n const buffer = Buffer.allocUnsafe(chunkSize);\n const { bytesRead } = await handle.read(buffer, 0, chunkSize, position - chunkSize);\n if (bytesRead < chunkSize) {\n // The file shrank under us. Bytes from `position` on are still a\n // contiguous suffix, so keep those and stop — splicing this short chunk in\n // would leave a hole (and, with an alloc'd buffer, NULs) mid-content.\n // `position` stays put, so the result is reported as having more lines.\n break;\n }\n position -= chunkSize;\n\n for (const byte of buffer) {\n if (byte === 0x0a) newlines++;\n }\n\n chunks.unshift(buffer);\n totalLen += chunkSize;\n\n // One newline more than `tail`: the oldest segment in the buffer starts\n // mid-line whenever we stop before the file start, and gets dropped below.\n if (newlines > tail) break;\n if (totalLen > options.maxSize) {\n stoppedByLimit = true;\n break;\n }\n }\n\n const allBytes = Buffer.concat(chunks, totalLen);\n let lines = allBytes.toString(encoding).split('\\n');\n\n // A trailing newline produces a spurious empty final segment; drop it.\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines = lines.slice(0, -1);\n }\n // Normalize CRLF.\n lines = lines.map((l) => (l.endsWith('\\r') ? l.slice(0, -1) : l));\n\n // We stopped before the file start, so the first segment is the tail of a\n // line whose beginning was never read. Drop it instead of reporting a\n // fragment as a complete line.\n if (position > 0 && lines.length > 0) {\n lines = lines.slice(1);\n }\n\n if (stoppedByLimit && lines.length < tail) {\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (${totalLen} > ${options.maxSize} bytes, could not collect ${tail} lines). Use a narrower tail or head.`,\n filePath,\n );\n }\n\n let hasMoreLines = stoppedByLimit || position > 0;\n if (lines.length > tail) {\n hasMoreLines = true;\n lines = lines.slice(lines.length - tail);\n }\n\n const content = lines.join('\\n');\n return {\n content,\n truncated: hasMoreLines,\n linesRead: lines.length,\n hasMoreLines,\n };\n}\n\nasync function readFullContent(\n handle: FileHandle,\n encoding: BufferEncoding,\n maxSize: number,\n requestedPath: string,\n signal?: AbortSignal,\n): Promise<{ content: string; totalLines: number }> {\n const buffer = await readFileBufferWithLimit(handle, maxSize, requestedPath, signal);\n const content = buffer.toString(encoding);\n return { content, totalLines: countLines(content) };\n}\n\nasync function assertNotBinary(\n validPath: string,\n filePath: string,\n handle: FileHandle,\n normalized: NormalizedBase,\n): Promise<void> {\n normalized.signal?.throwIfAborted();\n const isBinary = await isProbablyBinary(validPath, handle, normalized.signal);\n if (!isBinary) return;\n throw new FsError(ErrorCode.INVALID_INPUT, 'Binary file detected.', filePath);\n}\n\nfunction assertSizeWithinLimit(size: number, maxSize: number, filePath: string): void {\n if (size <= maxSize) return;\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (${size} > ${maxSize} bytes). Use head to preview.`,\n filePath,\n );\n}\n\ninterface ReadModeContext {\n handle: FileHandle;\n validPath: string;\n filePath: string;\n stats: Stats;\n spec: NormalizedSpec;\n}\n\nasync function readHead(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'head' }>,\n): Promise<ReadFileResult> {\n const contentOptions = buildReadContentOptions(spec);\n const { content, truncated, linesRead, hasMoreLines } = await readRangeContent(\n context.handle,\n 1,\n spec.lines,\n contentOptions,\n context.filePath,\n );\n\n return {\n path: context.validPath,\n content,\n truncated,\n readMode: 'head',\n head: spec.lines,\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readRange(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'range' }>,\n): Promise<ReadFileResult> {\n const contentOptions = buildReadContentOptions(spec);\n const { content, truncated, linesRead, hasMoreLines } = await readRangeContent(\n context.handle,\n spec.start,\n spec.end,\n contentOptions,\n context.filePath,\n );\n\n return {\n path: context.validPath,\n content,\n truncated,\n readMode: 'range',\n startLine: spec.start,\n ...(spec.end !== undefined ? { endLine: spec.end } : {}),\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readFull(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'full' }>,\n): Promise<ReadFileResult> {\n assertSizeWithinLimit(context.stats.size, spec.maxSize, context.filePath);\n const { content, totalLines } = await readFullContent(\n context.handle,\n spec.encoding,\n spec.maxSize,\n context.filePath,\n spec.signal,\n );\n\n return {\n path: context.validPath,\n content,\n truncated: false,\n totalLines,\n readMode: 'full',\n linesRead: totalLines,\n hasMoreLines: false,\n };\n}\n\nasync function readTail(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'tail' }>,\n): Promise<ReadFileResult> {\n const contentOptions = buildReadContentOptions(spec);\n const { content, truncated, linesRead, hasMoreLines } = await readTailContent(\n context.handle,\n spec.lines,\n contentOptions,\n context.validPath,\n );\n\n return {\n path: context.validPath,\n content,\n truncated,\n readMode: 'tail',\n tail: spec.lines,\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readByMode(context: ReadModeContext): Promise<ReadFileResult> {\n switch (context.spec.kind) {\n case 'head':\n return readHead(context, context.spec);\n case 'range':\n return readRange(context, context.spec);\n case 'full':\n return readFull(context, context.spec);\n case 'tail':\n return readTail(context, context.spec);\n default: {\n const _exhaustive: never = context.spec;\n return _exhaustive;\n }\n }\n}\n\nexport function assertFileStats(filePath: string, stats: Stats): void {\n if (!stats.isFile()) {\n throw new FsError(ErrorCode.NOT_FILE, 'Not a regular file', filePath);\n }\n}\n\nexport async function readNormalized(\n filePath: string,\n validPath: string,\n stats: Stats,\n spec: NormalizedSpec,\n): Promise<ReadFileResult> {\n spec.signal?.throwIfAborted();\n\n assertFileStats(filePath, stats);\n\n await using handle = await openReadableFileHandle(validPath, spec.signal);\n\n if (spec.skipBinary) {\n await assertNotBinary(validPath, filePath, handle, spec);\n }\n spec.signal?.throwIfAborted();\n\n return await readByMode({ handle, validPath, filePath, stats, spec });\n}\n\nexport async function readFileWithStats(\n filePath: string,\n validPath: string,\n stats: Stats,\n spec: ReadSpec | undefined,\n): Promise<ReadFileResult> {\n return readNormalized(filePath, validPath, stats, normalizeSpec(spec ?? { kind: 'full' }));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"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","sourcesContent":["// File reading pipeline split out of fs.ts. fs.ts imports from here; never the reverse.\nimport type { Stats } from 'node:fs';\nimport { open as fsOpen } from 'node:fs/promises';\nimport type { FileHandle } from 'node:fs/promises';\nimport { StringDecoder } from 'node:string_decoder';\n\nimport { withAbort } from './concurrency.js';\nimport { ErrorCode, formatUnknownErrorMessage, FsError, isFsError } from './errors.js';\nimport { isBinarySample, isKnownBinaryExtension, MIME_SAMPLE_SIZE } from './mime.js';\nimport { Logger } from './observability.js';\nimport { getMaxTextFileSize } from './util.js';\n\nconst STREAM_CHUNK_SIZE = 64 * 1024;\n\nconst READ_ONLY_FILE_FLAG = 'r';\n\nfunction assertPositiveIntegerOption(name: string, value: unknown, message?: string): void {\n if (\n value === undefined ||\n (typeof value === 'number' && Number.isSafeInteger(value) && value >= 1)\n )\n return;\n throw new FsError(ErrorCode.INVALID_INPUT, message ?? `${name} must be a positive integer`);\n}\n\nasync function openReadableFileHandle(filePath: string, signal?: AbortSignal): Promise<FileHandle> {\n const handlePromise = fsOpen(filePath, READ_ONLY_FILE_FLAG);\n if (!signal) return handlePromise;\n try {\n return await withAbort(handlePromise, signal);\n } catch (error) {\n void handlePromise\n .then((handle) => {\n void handle.close().catch((closeErr: unknown) => {\n Logger.warn(\n `Failed to close file handle for ${filePath} after abort: ${formatUnknownErrorMessage(closeErr)}`,\n );\n });\n })\n .catch(() => {\n /* ignore open error */\n });\n throw error;\n }\n}\n\nasync function readProbe(handle: FileHandle, signal?: AbortSignal): Promise<Buffer> {\n const buffer = Buffer.allocUnsafe(MIME_SAMPLE_SIZE);\n const { bytesRead } = await withAbort(handle.read(buffer, 0, MIME_SAMPLE_SIZE, 0), signal);\n\n if (bytesRead === 0) {\n return Buffer.alloc(0);\n }\n\n return buffer.subarray(0, bytesRead);\n}\n\nasync function isProbablyBinary(\n filePath: string,\n existingHandle?: FileHandle,\n signal?: AbortSignal,\n): Promise<boolean> {\n if (isKnownBinaryExtension(filePath)) {\n return true;\n }\n\n if (existingHandle) {\n const slice = await readProbe(existingHandle, signal);\n return isBinarySample(slice);\n }\n\n await using handle = await openReadableFileHandle(filePath, signal);\n const slice = await readProbe(handle, signal);\n return isBinarySample(slice);\n}\n\nexport type ReadSpec =\n | { kind: 'full'; signal?: AbortSignal }\n | { kind: 'head'; lines: number; signal?: AbortSignal }\n | { kind: 'tail'; lines: number; signal?: AbortSignal }\n | { kind: 'range'; start: number; end?: number; signal?: AbortSignal };\n\ninterface NormalizedBase {\n maxSize: number;\n signal?: AbortSignal;\n}\n\ntype NormalizedSpec =\n | (NormalizedBase & { kind: 'full' })\n | (NormalizedBase & { kind: 'head'; lines: number })\n | (NormalizedBase & { kind: 'tail'; lines: number })\n | (NormalizedBase & { kind: 'range'; start: number; end?: number });\n\ninterface PartialReadResult {\n content: string;\n linesRead: number;\n hasMoreLines: boolean;\n}\n\nexport interface ReadFileResult {\n path: string;\n content: string;\n totalLines?: number;\n readMode: ReadSpec['kind'];\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n}\n\nfunction buildBaseOptions(spec: ReadSpec): NormalizedBase {\n return {\n maxSize: getMaxTextFileSize(),\n ...(spec.signal ? { signal: spec.signal } : {}),\n };\n}\n\nfunction normalizeRangeSpec(\n spec: Extract<ReadSpec, { kind: 'range' }>,\n base: NormalizedBase,\n): NormalizedSpec {\n assertPositiveIntegerOption('start', spec.start, 'start must be at least 1');\n if (spec.end !== undefined) {\n assertPositiveIntegerOption('end', spec.end, 'end must be at least 1');\n if (spec.end < spec.start) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n 'end must be greater than or equal to start (default: 1)',\n );\n }\n }\n return {\n ...base,\n kind: 'range',\n start: spec.start,\n ...(spec.end !== undefined ? { end: spec.end } : {}),\n };\n}\n\nexport function normalizeSpec(spec: ReadSpec): NormalizedSpec {\n const base = buildBaseOptions(spec);\n spec.signal?.throwIfAborted();\n\n switch (spec.kind) {\n case 'head':\n case 'tail':\n assertPositiveIntegerOption('lines', spec.lines, 'lines must be at least 1');\n return { ...base, kind: spec.kind, lines: spec.lines };\n case 'range':\n return normalizeRangeSpec(spec, base);\n case 'full':\n return { ...base, kind: 'full' };\n default: {\n const _exhaustive: never = spec;\n return _exhaustive;\n }\n }\n}\n\nexport function createTooLargeError(\n bytesRead: number,\n maxSize: number,\n requestedPath: string,\n): FsError {\n return new FsError(\n ErrorCode.TOO_LARGE,\n `File exceeds size limit (${bytesRead} > ${maxSize} bytes)`,\n requestedPath,\n );\n}\n\nexport async function readFileBufferWithLimit(\n handle: FileHandle,\n maxSize: number,\n requestedPath: string,\n signal?: AbortSignal,\n): Promise<Buffer> {\n const stream = handle.createReadStream({\n start: 0,\n highWaterMark: STREAM_CHUNK_SIZE,\n autoClose: false,\n emitClose: false,\n signal,\n });\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n\n try {\n for await (const chunk of stream) {\n const buffer = chunk as Buffer;\n totalSize += buffer.length;\n\n if (totalSize > maxSize) {\n stream.destroy();\n throw createTooLargeError(totalSize, maxSize, requestedPath);\n }\n\n chunks.push(buffer);\n }\n } finally {\n if (!stream.destroyed) {\n stream.on('error', (_err: unknown) => {\n /* suppress post-destroy error event */\n });\n stream.destroy();\n }\n }\n\n return Buffer.concat(chunks, totalSize);\n}\n\nexport const countLines = (content: string): number => {\n if (content.length === 0) return 0;\n const trimmed = content.endsWith('\\n') ? content.slice(0, -1) : content;\n return trimmed.split('\\n').length;\n};\n\nasync function peekHasMore(iterator: AsyncIterator<string>): Promise<boolean> {\n try {\n const { done } = await iterator.next();\n return !done;\n } catch (error) {\n // The peek only asks \"is there another line\", and the caller keeps nothing\n // it returns. An over-long line past the requested range still answers yes\n // — failing the whole read over a line outside it would reject e.g. lines\n // 1-2 of a file whose line 3 is one 50 KB blob.\n if (isFsError(error) && error.code === ErrorCode.TOO_LARGE) return true;\n throw error;\n }\n}\n\nconst LF = 0x0a;\n\nfunction stripCarriageReturn(line: string): string {\n return line.endsWith('\\r') ? line.slice(0, -1) : line;\n}\n\n/**\n * Line iterator bounded by bytes rather than by the decoded string, so a file\n * that is one enormous line cannot be materialized before the size check runs.\n * `handle.readLines` decodes the whole line first and can OOM on such a file.\n *\n * Yields lines from `startLine` onward, 1-indexed. Lines before `startLine` are\n * counted and discarded without accumulating, so an over-long line the caller\n * skipped past does not fail the read. Line endings match `readLines`: split on\n * `\\n`, with a preceding `\\r` stripped, so CRLF input decodes identically.\n */\nasync function* readLinesBounded(\n handle: FileHandle,\n options: NormalizedBase,\n filePath: string,\n startLine: number,\n): AsyncGenerator<string, void, undefined> {\n const stream = handle.createReadStream({\n start: 0,\n highWaterMark: STREAM_CHUNK_SIZE,\n autoClose: false,\n emitClose: false,\n ...(options.signal ? { signal: options.signal } : {}),\n });\n\n const decoder = new StringDecoder('utf-8');\n let pending = '';\n let pendingBytes = 0;\n let lineNumber = 0;\n\n const tooLong = (bytes: number): FsError =>\n new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (single line ${bytes} > ${options.maxSize} bytes). Use a narrower range or head.`,\n filePath,\n );\n\n try {\n for await (const chunk of stream) {\n const buffer = chunk as Buffer;\n let offset = 0;\n\n // Search loop: each iteration finds the next LF and advances offset past\n // it. Written as while-with-assignment so the re-search is visible, rather\n // than buried in a for \"increment\" slot that re-runs indexOf.\n let nl = buffer.indexOf(LF, offset);\n while (nl !== -1) {\n const segment = buffer.subarray(offset, nl);\n const lineBytes = pendingBytes + segment.length;\n lineNumber++;\n // Decode even when skipping: the decoder carries multi-byte\n // continuation state into the first line the caller keeps.\n const decoded = decoder.write(segment);\n if (lineNumber >= startLine) {\n if (lineBytes > options.maxSize) throw tooLong(lineBytes);\n yield stripCarriageReturn(pending + decoded);\n }\n pending = '';\n pendingBytes = 0;\n offset = nl + 1;\n nl = buffer.indexOf(LF, offset);\n }\n\n const rest = buffer.subarray(offset);\n pendingBytes += rest.length;\n if (lineNumber + 1 < startLine) {\n decoder.write(rest); // still skipping; drop the text, keep decoder state\n } else {\n if (pendingBytes > options.maxSize) throw tooLong(pendingBytes);\n pending += decoder.write(rest);\n }\n }\n\n // Trailing line with no final newline. A file ending in `\\n` leaves\n // pendingBytes at 0 and emits nothing, matching readLines.\n if (pendingBytes > 0) {\n lineNumber++;\n if (lineNumber >= startLine) {\n if (pendingBytes > options.maxSize) throw tooLong(pendingBytes);\n yield pending + decoder.end();\n }\n }\n } finally {\n if (!stream.destroyed) {\n stream.on('error', (_err: unknown) => {\n /* suppress post-destroy error event */\n });\n stream.destroy();\n }\n }\n}\n\nasync function readRangeContent(\n handle: FileHandle,\n startLine: number,\n endLine: number | undefined,\n options: NormalizedBase,\n filePath: string,\n): Promise<PartialReadResult> {\n options.signal?.throwIfAborted();\n\n const lines: string[] = [];\n let lineNumber = startLine - 1;\n let estimatedBytes = 0;\n const newlineBytes = Buffer.byteLength('\\n', 'utf-8');\n const stopAt = endLine ?? Number.POSITIVE_INFINITY;\n\n let hasMoreLines = false;\n\n // Byte-bounded: an over-long line throws TOO_LARGE while still a partial\n // buffer, before it can be decoded into one huge string.\n const iterator = readLinesBounded(handle, options, filePath, startLine)[Symbol.asyncIterator]();\n\n try {\n for (;;) {\n const { value: line, done } = await iterator.next();\n if (done) {\n break;\n }\n lineNumber++;\n\n if (lineNumber > stopAt) {\n hasMoreLines = true;\n break;\n }\n\n lines.push(line);\n\n estimatedBytes += Buffer.byteLength(line, 'utf-8') + newlineBytes;\n if (estimatedBytes > options.maxSize) {\n hasMoreLines = await peekHasMore(iterator);\n break;\n }\n\n if (lineNumber === stopAt) {\n hasMoreLines = await peekHasMore(iterator);\n break;\n }\n }\n } finally {\n await iterator.return();\n }\n\n return {\n content: lines.join('\\n'),\n linesRead: lines.length,\n hasMoreLines,\n };\n}\n\nasync function readTailContent(\n handle: FileHandle,\n tail: number,\n options: NormalizedBase,\n filePath: string,\n): Promise<PartialReadResult> {\n options.signal?.throwIfAborted();\n\n const stats = await handle.stat();\n const fileSize = stats.size;\n if (fileSize === 0) {\n return {\n content: '',\n linesRead: 0,\n hasMoreLines: false,\n };\n }\n\n const encoding = 'utf-8';\n // Accumulate raw bytes from the end: decoding a chunk ending mid-codepoint\n // corrupts the trailing UTF-8 sequence into U+FFFD. 0x0A is single-byte and\n // never part of a multibyte sequence, so count newlines on the raw buffer and\n // decode the whole bounded buffer once at the end.\n let position = fileSize;\n const chunks: Buffer[] = [];\n let totalLen = 0;\n let newlines = 0;\n let stoppedByLimit = false;\n\n while (position > 0) {\n options.signal?.throwIfAborted();\n const chunkSize = Math.min(position, STREAM_CHUNK_SIZE);\n const buffer = Buffer.allocUnsafe(chunkSize);\n const { bytesRead } = await handle.read(buffer, 0, chunkSize, position - chunkSize);\n if (bytesRead < chunkSize) {\n // The file shrank under us. Bytes from `position` on are still a\n // contiguous suffix, so keep those and stop — splicing this short chunk in\n // would leave a hole (and, with an alloc'd buffer, NULs) mid-content.\n // `position` stays put, so the result is reported as having more lines.\n break;\n }\n position -= chunkSize;\n\n for (const byte of buffer) {\n if (byte === 0x0a) newlines++;\n }\n\n chunks.unshift(buffer);\n totalLen += chunkSize;\n\n // One newline more than `tail`: the oldest segment in the buffer starts\n // mid-line whenever we stop before the file start, and gets dropped below.\n if (newlines > tail) break;\n if (totalLen > options.maxSize) {\n stoppedByLimit = true;\n break;\n }\n }\n\n const allBytes = Buffer.concat(chunks, totalLen);\n let lines = allBytes.toString(encoding).split('\\n');\n\n // A trailing newline produces a spurious empty final segment; drop it.\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines = lines.slice(0, -1);\n }\n // Normalize CRLF.\n lines = lines.map((l) => (l.endsWith('\\r') ? l.slice(0, -1) : l));\n\n // We stopped before the file start, so the first segment is the tail of a\n // line whose beginning was never read. Drop it instead of reporting a\n // fragment as a complete line.\n if (position > 0 && lines.length > 0) {\n lines = lines.slice(1);\n }\n\n if (stoppedByLimit && lines.length < tail) {\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (${totalLen} > ${options.maxSize} bytes, could not collect ${tail} lines). Use a narrower tail or head.`,\n filePath,\n );\n }\n\n let hasMoreLines = stoppedByLimit || position > 0;\n if (lines.length > tail) {\n hasMoreLines = true;\n lines = lines.slice(lines.length - tail);\n }\n\n const content = lines.join('\\n');\n return {\n content,\n linesRead: lines.length,\n hasMoreLines,\n };\n}\n\nasync function readFullContent(\n handle: FileHandle,\n maxSize: number,\n requestedPath: string,\n signal?: AbortSignal,\n): Promise<{ content: string; totalLines: number }> {\n const buffer = await readFileBufferWithLimit(handle, maxSize, requestedPath, signal);\n const content = buffer.toString('utf-8');\n return { content, totalLines: countLines(content) };\n}\n\nasync function assertNotBinary(\n validPath: string,\n filePath: string,\n handle: FileHandle,\n normalized: NormalizedBase,\n): Promise<void> {\n normalized.signal?.throwIfAborted();\n const isBinary = await isProbablyBinary(validPath, handle, normalized.signal);\n if (!isBinary) return;\n throw new FsError(ErrorCode.INVALID_INPUT, 'Binary file detected.', filePath);\n}\n\nfunction assertSizeWithinLimit(size: number, maxSize: number, filePath: string): void {\n if (size <= maxSize) return;\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large (${size} > ${maxSize} bytes). Use head to preview.`,\n filePath,\n );\n}\n\ninterface ReadModeContext {\n handle: FileHandle;\n validPath: string;\n filePath: string;\n stats: Stats;\n spec: NormalizedSpec;\n}\n\nasync function readHead(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'head' }>,\n): Promise<ReadFileResult> {\n const { content, linesRead, hasMoreLines } = await readRangeContent(\n context.handle,\n 1,\n spec.lines,\n spec,\n context.filePath,\n );\n\n return {\n path: context.validPath,\n content,\n readMode: 'head',\n head: spec.lines,\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readRange(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'range' }>,\n): Promise<ReadFileResult> {\n const { content, linesRead, hasMoreLines } = await readRangeContent(\n context.handle,\n spec.start,\n spec.end,\n spec,\n context.filePath,\n );\n\n return {\n path: context.validPath,\n content,\n readMode: 'range',\n startLine: spec.start,\n ...(spec.end !== undefined ? { endLine: spec.end } : {}),\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readFull(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'full' }>,\n): Promise<ReadFileResult> {\n assertSizeWithinLimit(context.stats.size, spec.maxSize, context.filePath);\n const { content, totalLines } = await readFullContent(\n context.handle,\n spec.maxSize,\n context.filePath,\n spec.signal,\n );\n\n return {\n path: context.validPath,\n content,\n totalLines,\n readMode: 'full',\n linesRead: totalLines,\n hasMoreLines: false,\n };\n}\n\nasync function readTail(\n context: ReadModeContext,\n spec: Extract<NormalizedSpec, { kind: 'tail' }>,\n): Promise<ReadFileResult> {\n const { content, linesRead, hasMoreLines } = await readTailContent(\n context.handle,\n spec.lines,\n spec,\n context.validPath,\n );\n\n return {\n path: context.validPath,\n content,\n readMode: 'tail',\n tail: spec.lines,\n linesRead,\n hasMoreLines,\n };\n}\n\nasync function readByMode(context: ReadModeContext): Promise<ReadFileResult> {\n switch (context.spec.kind) {\n case 'head':\n return readHead(context, context.spec);\n case 'range':\n return readRange(context, context.spec);\n case 'full':\n return readFull(context, context.spec);\n case 'tail':\n return readTail(context, context.spec);\n default: {\n const _exhaustive: never = context.spec;\n return _exhaustive;\n }\n }\n}\n\nexport function assertFileStats(filePath: string, stats: Stats): void {\n if (!stats.isFile()) {\n throw new FsError(ErrorCode.NOT_FILE, 'Not a regular file', filePath);\n }\n}\n\nexport async function readNormalized(\n filePath: string,\n validPath: string,\n stats: Stats,\n spec: NormalizedSpec,\n): Promise<ReadFileResult> {\n spec.signal?.throwIfAborted();\n\n assertFileStats(filePath, stats);\n\n await using handle = await openReadableFileHandle(validPath, spec.signal);\n\n await assertNotBinary(validPath, filePath, handle, spec);\n spec.signal?.throwIfAborted();\n\n return await readByMode({ handle, validPath, filePath, stats, spec });\n}\n\nexport async function readFileWithStats(\n filePath: string,\n validPath: string,\n stats: Stats,\n spec: ReadSpec | undefined,\n): Promise<ReadFileResult> {\n return readNormalized(filePath, validPath, stats, normalizeSpec(spec ?? { kind: 'full' }));\n}\n"]}
|
package/dist/core/schema.d.ts
CHANGED
|
@@ -64,18 +64,6 @@ export declare const PathFailureSchema: z.ZodObject<{
|
|
|
64
64
|
suggestion: z.ZodOptional<z.ZodString>;
|
|
65
65
|
}, z.core.$strict>;
|
|
66
66
|
}, z.core.$strict>;
|
|
67
|
-
interface ReadRangeDescriptions {
|
|
68
|
-
head: string;
|
|
69
|
-
tail: string;
|
|
70
|
-
startLine: string;
|
|
71
|
-
endLine: string;
|
|
72
|
-
}
|
|
73
|
-
export declare function createReadRangeFields(descs: ReadRangeDescriptions): {
|
|
74
|
-
head: z.ZodOptional<z.ZodInt32>;
|
|
75
|
-
tail: z.ZodOptional<z.ZodInt32>;
|
|
76
|
-
startLine: z.ZodOptional<z.ZodInt32>;
|
|
77
|
-
endLine: z.ZodOptional<z.ZodInt32>;
|
|
78
|
-
};
|
|
79
67
|
export declare function validateReadRange(value: {
|
|
80
68
|
head?: number | undefined;
|
|
81
69
|
tail?: number | undefined;
|
|
@@ -90,10 +78,7 @@ export type SingleOrBatchShape<TExtra extends z.ZodRawShape> = TExtra & {
|
|
|
90
78
|
path: z.ZodOptional<typeof RequiredPath>;
|
|
91
79
|
paths: z.ZodOptional<z.ZodArray<typeof RequiredPath>>;
|
|
92
80
|
};
|
|
93
|
-
export declare function singleOrBatchPathsInput<TExtra extends z.ZodRawShape>(
|
|
94
|
-
extra: TExtra;
|
|
95
|
-
maxBatch?: number;
|
|
96
|
-
}): z.ZodObject<SingleOrBatchShape<TExtra>>;
|
|
81
|
+
export declare function singleOrBatchPathsInput<TExtra extends z.ZodRawShape>(extra: TExtra): z.ZodObject<SingleOrBatchShape<TExtra>>;
|
|
97
82
|
/**
|
|
98
83
|
* Extract the filesystem paths from a {@link singleOrBatchPathsInput} shape
|
|
99
84
|
* (`{ path?, paths?, files?[{path}] }`) for the executor's access-grant
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAY5B,eAAO,MAAM,WAAW,kBAMtB,CAAC;AAIH,eAAO,MAAM,SAAS,aAG2D,CAAC;AAElF,eAAO,MAAM,SAAS,UAEoB,CAAC;AAE3C,eAAO,MAAM,WAAW,UAEe,CAAC;AAExC,QAAA,MAAM,UAAU,oDAAc,CAAC;AAC/B,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,eAAO,MAAM,QAAQ;;;;;EAAqB,CAAC;AAE3C,QAAA,MAAM,UAAU,sDAAa,CAAC;AAC9B,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,eAAO,MAAM,QAAQ;;;;;;EAAqB,CAAC;AAM3C,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,KAAG,OAAkC,CAAC;AA6CzE,eAAO,MAAM,YAAY,4BAAsB,CAAC;AAChD,eAAO,MAAM,YAAY,aAAW,CAAC;AAErC,eAAO,MAAM,eAAe,aA0CmC,CAAC;AAKhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;kBAgBzB,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;kBAIjC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;kBAK7B,CAAC;AAEH,wEAAwE;AACxE,eAAO,MAAM,iBAAiB;;;;;;;;kBAG5B,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/core/schema.js
CHANGED
|
@@ -157,20 +157,6 @@ export const PathFailureSchema = z.strictObject({
|
|
|
157
157
|
path: z.string(),
|
|
158
158
|
error: PerFileErrorSchema,
|
|
159
159
|
});
|
|
160
|
-
export function createReadRangeFields(descs) {
|
|
161
|
-
const rangeField = (d) => z
|
|
162
|
-
.int32()
|
|
163
|
-
.min(1, { message: 'Min: 1' })
|
|
164
|
-
.max(100000, { message: 'Max: 100,000' })
|
|
165
|
-
.optional()
|
|
166
|
-
.describe(d);
|
|
167
|
-
return {
|
|
168
|
-
head: rangeField(descs.head),
|
|
169
|
-
tail: rangeField(descs.tail),
|
|
170
|
-
startLine: rangeField(descs.startLine),
|
|
171
|
-
endLine: rangeField(descs.endLine),
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
160
|
export function validateReadRange(value, ctx) {
|
|
175
161
|
const hasHead = value.head !== undefined;
|
|
176
162
|
const hasTail = value.tail !== undefined;
|
|
@@ -180,12 +166,7 @@ export function validateReadRange(value, ctx) {
|
|
|
180
166
|
ctx.addIssue({
|
|
181
167
|
code: 'custom',
|
|
182
168
|
path: ['head'],
|
|
183
|
-
message: "Cannot use 'head' with 'startLine'/'endLine'",
|
|
184
|
-
params: {
|
|
185
|
-
rule: 'head_no_line_range',
|
|
186
|
-
conflictsWith: ['startLine', 'endLine'],
|
|
187
|
-
suggestion: "Use either 'head' alone or 'startLine'/'endLine' together.",
|
|
188
|
-
},
|
|
169
|
+
message: "Cannot use 'head' with 'startLine'/'endLine'. Use either 'head' alone or 'startLine'/'endLine' together.",
|
|
189
170
|
input: value,
|
|
190
171
|
});
|
|
191
172
|
}
|
|
@@ -193,12 +174,7 @@ export function validateReadRange(value, ctx) {
|
|
|
193
174
|
ctx.addIssue({
|
|
194
175
|
code: 'custom',
|
|
195
176
|
path: ['tail'],
|
|
196
|
-
message: "Cannot use 'tail' with 'head'/'startLine'/'endLine'",
|
|
197
|
-
params: {
|
|
198
|
-
rule: 'tail_exclusive',
|
|
199
|
-
conflictsWith: ['head', 'startLine', 'endLine'],
|
|
200
|
-
suggestion: "Use 'tail' alone or use 'startLine'/'endLine' without 'tail'.",
|
|
201
|
-
},
|
|
177
|
+
message: "Cannot use 'tail' with 'head'/'startLine'/'endLine'. Use 'tail' alone, or 'startLine'/'endLine' without 'tail'.",
|
|
202
178
|
input: value,
|
|
203
179
|
});
|
|
204
180
|
}
|
|
@@ -206,11 +182,7 @@ export function validateReadRange(value, ctx) {
|
|
|
206
182
|
ctx.addIssue({
|
|
207
183
|
code: 'custom',
|
|
208
184
|
path: ['endLine'],
|
|
209
|
-
message: "'endLine' requires 'startLine' to be set",
|
|
210
|
-
params: {
|
|
211
|
-
rule: 'endLine_requires_startLine',
|
|
212
|
-
suggestion: "Provide both 'startLine' and 'endLine' together.",
|
|
213
|
-
},
|
|
185
|
+
message: "'endLine' requires 'startLine' to be set. Provide both together.",
|
|
214
186
|
input: value,
|
|
215
187
|
});
|
|
216
188
|
}
|
|
@@ -220,11 +192,6 @@ export function validateReadRange(value, ctx) {
|
|
|
220
192
|
code: 'custom',
|
|
221
193
|
path: ['endLine'],
|
|
222
194
|
message: "'endLine' must be >= 'startLine'",
|
|
223
|
-
params: {
|
|
224
|
-
rule: 'endLine_gte_startLine',
|
|
225
|
-
conflictsWith: ['startLine'],
|
|
226
|
-
suggestion: 'Set endLine to a value greater than or equal to startLine.',
|
|
227
|
-
},
|
|
228
195
|
input: value,
|
|
229
196
|
});
|
|
230
197
|
}
|
|
@@ -241,17 +208,16 @@ export const maxDepthField = () => z
|
|
|
241
208
|
.optional()
|
|
242
209
|
.describe('Max directory depth to scan; 0 = base directory only, omit for unlimited');
|
|
243
210
|
const DEFAULT_MAX_BATCH = 1000;
|
|
244
|
-
export function singleOrBatchPathsInput(
|
|
245
|
-
const maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH;
|
|
211
|
+
export function singleOrBatchPathsInput(extra) {
|
|
246
212
|
const shape = {
|
|
247
|
-
...
|
|
213
|
+
...extra,
|
|
248
214
|
path: RequiredPath.optional().describe('Single file path; mutually exclusive with paths'),
|
|
249
215
|
paths: z
|
|
250
216
|
.array(RequiredPath)
|
|
251
217
|
.min(1)
|
|
252
|
-
.max(
|
|
218
|
+
.max(DEFAULT_MAX_BATCH)
|
|
253
219
|
.optional()
|
|
254
|
-
.describe(`Array of file paths for batch mode (max ${String(
|
|
220
|
+
.describe(`Array of file paths for batch mode (max ${String(DEFAULT_MAX_BATCH)}); mutually exclusive with path`),
|
|
255
221
|
};
|
|
256
222
|
const base = z.strictObject(shape).superRefine((value, ctx) => {
|
|
257
223
|
const hasPath = value['path'] !== undefined;
|
package/dist/core/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from 'zod/v4';\n\nimport { isSafeGlobSyntax } from './glob.js';\nimport { MIME_KINDS } from './mime.js';\nimport { ENTRY_TYPES } from './primitives.js';\nimport { MAX_SEARCH_DEPTH } from './util.js';\n\n// Runtime: full ISO-8601 UTC; emits the standard `date-time` format on the wire\n// (no AJV warning — it is a known format, unlike sha256_hex / base64url).\n// No `id` on this or any other shared schema below: an `id` hoists the schema\n// into `$defs` and leaves a `$ref` at every use site, which is exactly the wire\n// weight `toDraft202012` (tools/define.ts) publishes without.\nexport const IsoDateTime = z.iso.datetime().meta({\n description: 'ISO 8601 UTC date-time string (e.g. 2024-01-15T12:00:00.000Z)',\n // `format: \"date-time\"` already pins the value; zod's ~330-char calendar\n // regex is pure wire weight. Runtime validation still runs it — this\n // suppresses the emitted keyword only.\n pattern: undefined,\n});\n\n// pattern (not z.hash('sha256')) so no `format: \"sha256_hex\"` keyword is emitted;\n// the SDK's AJV validator warns on that unknown format at every server start.\nexport const Sha256Hex = z\n .string()\n .regex(/^[0-9a-f]{64}$/)\n .meta({ description: 'SHA-256 digest as a 64-character lowercase hex string' });\n\nexport const NonNegInt = z\n .int({ message: 'Must be integer' })\n .nonnegative({ message: 'Must be ≥ 0' });\n\nexport const PositiveInt = z\n .int({ message: 'Must be integer' })\n .positive({ message: 'Must be > 0' });\n\nconst FILE_TYPES = ENTRY_TYPES;\nexport type FileType = (typeof FILE_TYPES)[number];\nexport const FileType = z.enum(FILE_TYPES);\n\nconst FILE_KINDS = MIME_KINDS;\nexport type FileKind = (typeof FILE_KINDS)[number];\nexport const FileKind = z.enum(FILE_KINDS);\n\nconst MAX_PATH_LENGTH = 4096;\n\nconst SHELL_METACHAR_RE = /[\\n\\r;|`]/;\n\nexport const isBlank = (val: string): boolean => val.trim().length === 0;\n\nconst PathBase = z\n .string()\n .min(1, { message: 'Path required' })\n .max(MAX_PATH_LENGTH, { message: `Path too long (max ${MAX_PATH_LENGTH} chars)` })\n .superRefine((val, ctx) => {\n if (val.length === 0) {\n return;\n }\n if (val.trim().length === 0) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path cannot be empty or whitespace-only',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('\\0')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path cannot contain null bytes',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('..')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Directory traversal sequences (\"..\") are forbidden',\n fatal: true,\n });\n return z.NEVER;\n }\n if (SHELL_METACHAR_RE.test(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path contains prohibited characters (newlines or shell metacharacters)',\n fatal: true,\n });\n return z.NEVER;\n }\n })\n .describe('File or directory path inside an allowed workspace root.');\n\nexport const OptionalPath = PathBase.optional();\nexport const RequiredPath = PathBase;\n\nexport const SafeGlobPattern = z\n .string()\n .min(1, { message: 'Pattern required' })\n .max(1000, { message: 'Max 1000 chars' })\n .superRefine((val, ctx) => {\n if (val.length === 0) {\n return;\n }\n if (val.trim().length === 0) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern cannot be empty or whitespace-only',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('\\0')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern cannot contain null bytes',\n fatal: true,\n });\n return z.NEVER;\n }\n if (!isSafeGlobSyntax(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Invalid glob or unsafe path (absolute/.. forbidden)',\n fatal: true,\n });\n return z.NEVER;\n }\n if (SHELL_METACHAR_RE.test(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern contains prohibited characters (newlines or shell metacharacters)',\n fatal: true,\n });\n return z.NEVER;\n }\n })\n .describe('Relative glob pattern under the search root (e.g. \"**/*.ts\", \"src/**/*.js\").')\n .meta({ examples: ['**/*.ts', 'src/**/*.js', '*.{ts,tsx}'] });\n\n// Only the fields whose key does not already say what they hold carry a\n// description. A `.describe('Name')` on `name` costs every client tokens to\n// learn nothing.\nexport const FileInfoSchema = z.strictObject({\n name: z.string(),\n path: z.string(),\n type: FileType,\n // A directory's own inode size says nothing about what is inside it — 0 on\n // Windows, 4096 on ext4 — so say so rather than letting a caller read it as\n // \"empty\". This caveat used to live in stat's text summary, which is gone.\n size: NonNegInt.describe('Bytes; meaningless for a directory — use list for its contents'),\n tokenEstimate: NonNegInt.optional().describe('Rough token estimate; use to pre-screen read cost'),\n created: IsoDateTime,\n modified: IsoDateTime,\n accessed: IsoDateTime,\n permissions: z.string(),\n isHidden: z.boolean(),\n mimeType: z.string().optional(),\n symlinkTarget: z.string().optional().describe('Target (symlink)'),\n});\n\nexport const OperationSummarySchema = z.strictObject({\n total: NonNegInt,\n succeeded: NonNegInt,\n failed: NonNegInt,\n});\n\nexport const PerFileErrorSchema = z.strictObject({\n code: z.string(),\n message: z.string(),\n path: z.string().optional(),\n suggestion: z.string().optional(),\n});\n\n/** One entry of a tool's `failures[]`: the path that failed and why. */\nexport const PathFailureSchema = z.strictObject({\n path: z.string(),\n error: PerFileErrorSchema,\n});\n\n// TODO(future): Wrap createReadRangeFields output in a typed Zod object with built-in\n// cross-validation. Safe for now — the only caller (read.ts) calls validateReadRange in its own superRefine.\ninterface ReadRangeDescriptions {\n head: string;\n tail: string;\n startLine: string;\n endLine: string;\n}\n\nexport function createReadRangeFields(descs: ReadRangeDescriptions) {\n const rangeField = (d: string) =>\n z\n .int32()\n .min(1, { message: 'Min: 1' })\n .max(100000, { message: 'Max: 100,000' })\n .optional()\n .describe(d);\n return {\n head: rangeField(descs.head),\n tail: rangeField(descs.tail),\n startLine: rangeField(descs.startLine),\n endLine: rangeField(descs.endLine),\n };\n}\n\nexport function validateReadRange(\n value: {\n head?: number | undefined;\n tail?: number | undefined;\n startLine?: number | undefined;\n endLine?: number | undefined;\n },\n ctx: z.RefinementCtx,\n): void {\n const hasHead = value.head !== undefined;\n const hasTail = value.tail !== undefined;\n const hasStart = value.startLine !== undefined;\n const hasEnd = value.endLine !== undefined;\n\n if (hasHead && (hasStart || hasEnd)) {\n ctx.addIssue({\n code: 'custom',\n path: ['head'],\n message: \"Cannot use 'head' with 'startLine'/'endLine'\",\n params: {\n rule: 'head_no_line_range',\n conflictsWith: ['startLine', 'endLine'],\n suggestion: \"Use either 'head' alone or 'startLine'/'endLine' together.\",\n },\n input: value,\n });\n }\n if (hasTail && (hasHead || hasStart || hasEnd)) {\n ctx.addIssue({\n code: 'custom',\n path: ['tail'],\n message: \"Cannot use 'tail' with 'head'/'startLine'/'endLine'\",\n params: {\n rule: 'tail_exclusive',\n conflictsWith: ['head', 'startLine', 'endLine'],\n suggestion: \"Use 'tail' alone or use 'startLine'/'endLine' without 'tail'.\",\n },\n input: value,\n });\n }\n if (hasEnd && !hasStart) {\n ctx.addIssue({\n code: 'custom',\n path: ['endLine'],\n message: \"'endLine' requires 'startLine' to be set\",\n params: {\n rule: 'endLine_requires_startLine',\n suggestion: \"Provide both 'startLine' and 'endLine' together.\",\n },\n input: value,\n });\n }\n const effectiveStart = value.startLine ?? 1;\n if (value.endLine !== undefined && value.endLine < effectiveStart) {\n ctx.addIssue({\n code: 'custom',\n path: ['endLine'],\n message: \"'endLine' must be >= 'startLine'\",\n params: {\n rule: 'endLine_gte_startLine',\n conflictsWith: ['startLine'],\n suggestion: 'Set endLine to a value greater than or equal to startLine.',\n },\n input: value,\n });\n }\n}\n\nexport function defaultFalseBoolean(description: string): z.ZodDefault<z.ZodBoolean> {\n return z.boolean().default(false).describe(description);\n}\n\nexport const includeHiddenField = (): z.ZodDefault<z.ZodBoolean> =>\n defaultFalseBoolean('Include hidden items (starting with .)');\nexport const includeIgnoredField = (): z.ZodDefault<z.ZodBoolean> =>\n defaultFalseBoolean('Include ignored items (node_modules, .git, etc).');\nexport const maxDepthField = (): z.ZodOptional<z.ZodNumber> =>\n z\n .uint32()\n .min(0)\n .max(MAX_SEARCH_DEPTH)\n .optional()\n .describe('Max directory depth to scan; 0 = base directory only, omit for unlimited');\n\nconst DEFAULT_MAX_BATCH = 1000;\n\nexport type SingleOrBatchShape<TExtra extends z.ZodRawShape> = TExtra & {\n path: z.ZodOptional<typeof RequiredPath>;\n paths: z.ZodOptional<z.ZodArray<typeof RequiredPath>>;\n};\n\nexport function singleOrBatchPathsInput<TExtra extends z.ZodRawShape>(opts: {\n extra: TExtra;\n maxBatch?: number;\n}): z.ZodObject<SingleOrBatchShape<TExtra>> {\n const maxBatch = opts.maxBatch ?? DEFAULT_MAX_BATCH;\n\n const shape: z.ZodRawShape = {\n ...opts.extra,\n path: RequiredPath.optional().describe('Single file path; mutually exclusive with paths'),\n paths: z\n .array(RequiredPath)\n .min(1)\n .max(maxBatch)\n .optional()\n .describe(\n `Array of file paths for batch mode (max ${String(maxBatch)}); mutually exclusive with path`,\n ),\n };\n\n const base = z.strictObject(shape).superRefine((value, ctx) => {\n const hasPath = value['path'] !== undefined;\n const hasPaths = value['paths'] !== undefined;\n\n if (!hasPath && !hasPaths) {\n ctx.addIssue({\n code: 'custom',\n path: ['path'],\n message: \"Either 'path' or 'paths' must be provided\",\n input: value,\n });\n return;\n }\n if (hasPath && hasPaths) {\n ctx.addIssue({\n code: 'custom',\n path: ['paths'],\n message: \"Cannot use both 'path' and 'paths'\",\n input: value,\n });\n }\n });\n\n // Mirror the superRefine above on the wire: exactly one input mode. `{}` and\n // `path`+`paths` both fail this oneOf, matching the runtime rule.\n return base.meta({\n oneOf: [{ required: ['path'] }, { required: ['paths'] }],\n }) as z.ZodObject<SingleOrBatchShape<TExtra>>;\n}\n\n/**\n * Extract the filesystem paths from a {@link singleOrBatchPathsInput} shape\n * (`{ path?, paths?, files?[{path}] }`) for the executor's access-grant\n * pre-check. Exactly one of the three is set (enforced by the schema's\n * superRefine), so they are checked in priority order.\n */\nexport function singleOrBatchAccessPaths(args: {\n path?: string | undefined;\n paths?: string[] | undefined;\n files?: readonly { path: string }[] | undefined;\n}): string[] {\n if (args.path) return [args.path];\n if (args.paths) return [...args.paths];\n if (args.files) return args.files.map((f) => f.path);\n return [];\n}\n\n// `args` is the exact argument object the one producer (read's\n// buildReadContinuation) emits, not a free-form record: a bare\n// `z.record(z.string(), z.unknown())` renders as `additionalProperties: {}`,\n// which carries no validation keyword and constrains nothing — the Inspector's\n// portability check flags it, and a client cannot tell what to pass. Widen this\n// (to a union) only when a second tool starts emitting continuations.\nexport const ContinuationSchema = z.strictObject({\n tool: z.string().describe('Tool name to call for the next chunk'),\n args: z\n .strictObject({ path: z.string(), startLine: PositiveInt, endLine: PositiveInt })\n .describe('Ready-to-use arguments for the next call; pass verbatim'),\n hint: z.string().describe('One-sentence description of the data still remaining to be read'),\n});\n\n// ponytail: charset regex, not z.base64url() — the SDK's AJV warns on the\n// unknown `base64url` format; the server's own decode (cursor.ts) is the real\n// validation, so loosening the client-facing schema to the alphabet is safe.\nconst base64urlCursor = z.string().regex(/^[A-Za-z0-9_-]+$/);\n\n// Ships once per paginated tool — wording is budgeted (TOOL-SURFACE-002).\nexport const CursorSchema = base64urlCursor\n .optional()\n .describe(\n 'Opaque pagination cursor; pass unchanged for the next page. Pages slice one snapshot ' +\n 'taken on the first call; it expires after ~60s — re-request without a cursor if rejected.',\n );\n\nexport const NextCursorSchema = base64urlCursor\n .optional()\n .describe('Cursor for the next page; omitted when this is the final page.');\n"]}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from 'zod/v4';\n\nimport { isSafeGlobSyntax } from './glob.js';\nimport { MIME_KINDS } from './mime.js';\nimport { ENTRY_TYPES } from './primitives.js';\nimport { MAX_SEARCH_DEPTH } from './util.js';\n\n// Runtime: full ISO-8601 UTC; emits the standard `date-time` format on the wire\n// (no AJV warning — it is a known format, unlike sha256_hex / base64url).\n// No `id` on this or any other shared schema below: an `id` hoists the schema\n// into `$defs` and leaves a `$ref` at every use site, which is exactly the wire\n// weight `toDraft202012` (tools/define.ts) publishes without.\nexport const IsoDateTime = z.iso.datetime().meta({\n description: 'ISO 8601 UTC date-time string (e.g. 2024-01-15T12:00:00.000Z)',\n // `format: \"date-time\"` already pins the value; zod's ~330-char calendar\n // regex is pure wire weight. Runtime validation still runs it — this\n // suppresses the emitted keyword only.\n pattern: undefined,\n});\n\n// pattern (not z.hash('sha256')) so no `format: \"sha256_hex\"` keyword is emitted;\n// the SDK's AJV validator warns on that unknown format at every server start.\nexport const Sha256Hex = z\n .string()\n .regex(/^[0-9a-f]{64}$/)\n .meta({ description: 'SHA-256 digest as a 64-character lowercase hex string' });\n\nexport const NonNegInt = z\n .int({ message: 'Must be integer' })\n .nonnegative({ message: 'Must be ≥ 0' });\n\nexport const PositiveInt = z\n .int({ message: 'Must be integer' })\n .positive({ message: 'Must be > 0' });\n\nconst FILE_TYPES = ENTRY_TYPES;\nexport type FileType = (typeof FILE_TYPES)[number];\nexport const FileType = z.enum(FILE_TYPES);\n\nconst FILE_KINDS = MIME_KINDS;\nexport type FileKind = (typeof FILE_KINDS)[number];\nexport const FileKind = z.enum(FILE_KINDS);\n\nconst MAX_PATH_LENGTH = 4096;\n\nconst SHELL_METACHAR_RE = /[\\n\\r;|`]/;\n\nexport const isBlank = (val: string): boolean => val.trim().length === 0;\n\nconst PathBase = z\n .string()\n .min(1, { message: 'Path required' })\n .max(MAX_PATH_LENGTH, { message: `Path too long (max ${MAX_PATH_LENGTH} chars)` })\n .superRefine((val, ctx) => {\n if (val.length === 0) {\n return;\n }\n if (val.trim().length === 0) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path cannot be empty or whitespace-only',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('\\0')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path cannot contain null bytes',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('..')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Directory traversal sequences (\"..\") are forbidden',\n fatal: true,\n });\n return z.NEVER;\n }\n if (SHELL_METACHAR_RE.test(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Path contains prohibited characters (newlines or shell metacharacters)',\n fatal: true,\n });\n return z.NEVER;\n }\n })\n .describe('File or directory path inside an allowed workspace root.');\n\nexport const OptionalPath = PathBase.optional();\nexport const RequiredPath = PathBase;\n\nexport const SafeGlobPattern = z\n .string()\n .min(1, { message: 'Pattern required' })\n .max(1000, { message: 'Max 1000 chars' })\n .superRefine((val, ctx) => {\n if (val.length === 0) {\n return;\n }\n if (val.trim().length === 0) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern cannot be empty or whitespace-only',\n fatal: true,\n });\n return z.NEVER;\n }\n if (val.includes('\\0')) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern cannot contain null bytes',\n fatal: true,\n });\n return z.NEVER;\n }\n if (!isSafeGlobSyntax(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Invalid glob or unsafe path (absolute/.. forbidden)',\n fatal: true,\n });\n return z.NEVER;\n }\n if (SHELL_METACHAR_RE.test(val)) {\n ctx.addIssue({\n code: 'custom',\n message: 'Pattern contains prohibited characters (newlines or shell metacharacters)',\n fatal: true,\n });\n return z.NEVER;\n }\n })\n .describe('Relative glob pattern under the search root (e.g. \"**/*.ts\", \"src/**/*.js\").')\n .meta({ examples: ['**/*.ts', 'src/**/*.js', '*.{ts,tsx}'] });\n\n// Only the fields whose key does not already say what they hold carry a\n// description. A `.describe('Name')` on `name` costs every client tokens to\n// learn nothing.\nexport const FileInfoSchema = z.strictObject({\n name: z.string(),\n path: z.string(),\n type: FileType,\n // A directory's own inode size says nothing about what is inside it — 0 on\n // Windows, 4096 on ext4 — so say so rather than letting a caller read it as\n // \"empty\". This caveat used to live in stat's text summary, which is gone.\n size: NonNegInt.describe('Bytes; meaningless for a directory — use list for its contents'),\n tokenEstimate: NonNegInt.optional().describe('Rough token estimate; use to pre-screen read cost'),\n created: IsoDateTime,\n modified: IsoDateTime,\n accessed: IsoDateTime,\n permissions: z.string(),\n isHidden: z.boolean(),\n mimeType: z.string().optional(),\n symlinkTarget: z.string().optional().describe('Target (symlink)'),\n});\n\nexport const OperationSummarySchema = z.strictObject({\n total: NonNegInt,\n succeeded: NonNegInt,\n failed: NonNegInt,\n});\n\nexport const PerFileErrorSchema = z.strictObject({\n code: z.string(),\n message: z.string(),\n path: z.string().optional(),\n suggestion: z.string().optional(),\n});\n\n/** One entry of a tool's `failures[]`: the path that failed and why. */\nexport const PathFailureSchema = z.strictObject({\n path: z.string(),\n error: PerFileErrorSchema,\n});\n\nexport function validateReadRange(\n value: {\n head?: number | undefined;\n tail?: number | undefined;\n startLine?: number | undefined;\n endLine?: number | undefined;\n },\n ctx: z.RefinementCtx,\n): void {\n const hasHead = value.head !== undefined;\n const hasTail = value.tail !== undefined;\n const hasStart = value.startLine !== undefined;\n const hasEnd = value.endLine !== undefined;\n\n if (hasHead && (hasStart || hasEnd)) {\n ctx.addIssue({\n code: 'custom',\n path: ['head'],\n message:\n \"Cannot use 'head' with 'startLine'/'endLine'. Use either 'head' alone or 'startLine'/'endLine' together.\",\n input: value,\n });\n }\n if (hasTail && (hasHead || hasStart || hasEnd)) {\n ctx.addIssue({\n code: 'custom',\n path: ['tail'],\n message:\n \"Cannot use 'tail' with 'head'/'startLine'/'endLine'. Use 'tail' alone, or 'startLine'/'endLine' without 'tail'.\",\n input: value,\n });\n }\n if (hasEnd && !hasStart) {\n ctx.addIssue({\n code: 'custom',\n path: ['endLine'],\n message: \"'endLine' requires 'startLine' to be set. Provide both together.\",\n input: value,\n });\n }\n const effectiveStart = value.startLine ?? 1;\n if (value.endLine !== undefined && value.endLine < effectiveStart) {\n ctx.addIssue({\n code: 'custom',\n path: ['endLine'],\n message: \"'endLine' must be >= 'startLine'\",\n input: value,\n });\n }\n}\n\nexport function defaultFalseBoolean(description: string): z.ZodDefault<z.ZodBoolean> {\n return z.boolean().default(false).describe(description);\n}\n\nexport const includeHiddenField = (): z.ZodDefault<z.ZodBoolean> =>\n defaultFalseBoolean('Include hidden items (starting with .)');\nexport const includeIgnoredField = (): z.ZodDefault<z.ZodBoolean> =>\n defaultFalseBoolean('Include ignored items (node_modules, .git, etc).');\nexport const maxDepthField = (): z.ZodOptional<z.ZodNumber> =>\n z\n .uint32()\n .min(0)\n .max(MAX_SEARCH_DEPTH)\n .optional()\n .describe('Max directory depth to scan; 0 = base directory only, omit for unlimited');\n\nconst DEFAULT_MAX_BATCH = 1000;\n\nexport type SingleOrBatchShape<TExtra extends z.ZodRawShape> = TExtra & {\n path: z.ZodOptional<typeof RequiredPath>;\n paths: z.ZodOptional<z.ZodArray<typeof RequiredPath>>;\n};\n\nexport function singleOrBatchPathsInput<TExtra extends z.ZodRawShape>(\n extra: TExtra,\n): z.ZodObject<SingleOrBatchShape<TExtra>> {\n const shape: z.ZodRawShape = {\n ...extra,\n path: RequiredPath.optional().describe('Single file path; mutually exclusive with paths'),\n paths: z\n .array(RequiredPath)\n .min(1)\n .max(DEFAULT_MAX_BATCH)\n .optional()\n .describe(\n `Array of file paths for batch mode (max ${String(DEFAULT_MAX_BATCH)}); mutually exclusive with path`,\n ),\n };\n\n const base = z.strictObject(shape).superRefine((value, ctx) => {\n const hasPath = value['path'] !== undefined;\n const hasPaths = value['paths'] !== undefined;\n\n if (!hasPath && !hasPaths) {\n ctx.addIssue({\n code: 'custom',\n path: ['path'],\n message: \"Either 'path' or 'paths' must be provided\",\n input: value,\n });\n return;\n }\n if (hasPath && hasPaths) {\n ctx.addIssue({\n code: 'custom',\n path: ['paths'],\n message: \"Cannot use both 'path' and 'paths'\",\n input: value,\n });\n }\n });\n\n // Mirror the superRefine above on the wire: exactly one input mode. `{}` and\n // `path`+`paths` both fail this oneOf, matching the runtime rule.\n return base.meta({\n oneOf: [{ required: ['path'] }, { required: ['paths'] }],\n }) as z.ZodObject<SingleOrBatchShape<TExtra>>;\n}\n\n/**\n * Extract the filesystem paths from a {@link singleOrBatchPathsInput} shape\n * (`{ path?, paths?, files?[{path}] }`) for the executor's access-grant\n * pre-check. Exactly one of the three is set (enforced by the schema's\n * superRefine), so they are checked in priority order.\n */\nexport function singleOrBatchAccessPaths(args: {\n path?: string | undefined;\n paths?: string[] | undefined;\n files?: readonly { path: string }[] | undefined;\n}): string[] {\n if (args.path) return [args.path];\n if (args.paths) return [...args.paths];\n if (args.files) return args.files.map((f) => f.path);\n return [];\n}\n\n// `args` is the exact argument object the one producer (read's\n// buildReadContinuation) emits, not a free-form record: a bare\n// `z.record(z.string(), z.unknown())` renders as `additionalProperties: {}`,\n// which carries no validation keyword and constrains nothing — the Inspector's\n// portability check flags it, and a client cannot tell what to pass. Widen this\n// (to a union) only when a second tool starts emitting continuations.\nexport const ContinuationSchema = z.strictObject({\n tool: z.string().describe('Tool name to call for the next chunk'),\n args: z\n .strictObject({ path: z.string(), startLine: PositiveInt, endLine: PositiveInt })\n .describe('Ready-to-use arguments for the next call; pass verbatim'),\n hint: z.string().describe('One-sentence description of the data still remaining to be read'),\n});\n\n// ponytail: charset regex, not z.base64url() — the SDK's AJV warns on the\n// unknown `base64url` format; the server's own decode (cursor.ts) is the real\n// validation, so loosening the client-facing schema to the alphabet is safe.\nconst base64urlCursor = z.string().regex(/^[A-Za-z0-9_-]+$/);\n\n// Ships once per paginated tool — wording is budgeted (TOOL-SURFACE-002).\nexport const CursorSchema = base64urlCursor\n .optional()\n .describe(\n 'Opaque pagination cursor; pass unchanged for the next page. Pages slice one snapshot ' +\n 'taken on the first call; it expires after ~60s — re-request without a cursor if rejected.',\n );\n\nexport const NextCursorSchema = base64urlCursor\n .optional()\n .describe('Cursor for the next page; omitted when this is the final page.');\n"]}
|