@j0hanz/fs-context-mcp 2.0.7 → 2.1.1
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 +60 -12
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/instructions.md +27 -118
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/file-operations/file-info.d.ts.map +1 -1
- package/dist/lib/file-operations/file-info.js +2 -0
- package/dist/lib/file-operations/file-info.js.map +1 -1
- package/dist/lib/file-operations/gitignore.d.ts +6 -0
- package/dist/lib/file-operations/gitignore.d.ts.map +1 -0
- package/dist/lib/file-operations/gitignore.js +42 -0
- package/dist/lib/file-operations/gitignore.js.map +1 -0
- package/dist/lib/file-operations/read-multiple-files.d.ts +5 -1
- package/dist/lib/file-operations/read-multiple-files.d.ts.map +1 -1
- package/dist/lib/file-operations/read-multiple-files.js +48 -17
- package/dist/lib/file-operations/read-multiple-files.js.map +1 -1
- package/dist/lib/file-operations/search-content-scan.d.ts +29 -0
- package/dist/lib/file-operations/search-content-scan.d.ts.map +1 -0
- package/dist/lib/file-operations/search-content-scan.js +468 -0
- package/dist/lib/file-operations/search-content-scan.js.map +1 -0
- package/dist/lib/file-operations/search-content-worker-api.d.ts +56 -0
- package/dist/lib/file-operations/search-content-worker-api.d.ts.map +1 -0
- package/dist/lib/file-operations/search-content-worker-api.js +239 -0
- package/dist/lib/file-operations/search-content-worker-api.js.map +1 -0
- package/dist/lib/file-operations/search-content.d.ts.map +1 -1
- package/dist/lib/file-operations/search-content.js +59 -53
- package/dist/lib/file-operations/search-content.js.map +1 -1
- package/dist/lib/file-operations/search-files.d.ts +1 -0
- package/dist/lib/file-operations/search-files.d.ts.map +1 -1
- package/dist/lib/file-operations/search-files.js +11 -2
- package/dist/lib/file-operations/search-files.js.map +1 -1
- package/dist/lib/file-operations/tree.d.ts +25 -0
- package/dist/lib/file-operations/tree.d.ts.map +1 -0
- package/dist/lib/file-operations/tree.js +172 -0
- package/dist/lib/file-operations/tree.js.map +1 -0
- package/dist/lib/fs-helpers.d.ts +5 -1
- package/dist/lib/fs-helpers.d.ts.map +1 -1
- package/dist/lib/fs-helpers.js +131 -14
- package/dist/lib/fs-helpers.js.map +1 -1
- package/dist/lib/path-validation.d.ts.map +1 -1
- package/dist/lib/path-validation.js +15 -17
- package/dist/lib/path-validation.js.map +1 -1
- package/dist/lib/resource-store.d.ts +23 -0
- package/dist/lib/resource-store.d.ts.map +1 -0
- package/dist/lib/resource-store.js +75 -0
- package/dist/lib/resource-store.js.map +1 -0
- package/dist/lib/strict-stdio-transport.d.ts +31 -0
- package/dist/lib/strict-stdio-transport.d.ts.map +1 -0
- package/dist/lib/strict-stdio-transport.js +158 -0
- package/dist/lib/strict-stdio-transport.js.map +1 -0
- package/dist/resources.d.ts +5 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +43 -0
- package/dist/resources.js.map +1 -0
- package/dist/schemas.d.ts +78 -12
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +125 -24
- package/dist/schemas.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +52 -11
- package/dist/server.js.map +1 -1
- package/dist/tooling/tool-response.d.ts +32 -0
- package/dist/tooling/tool-response.d.ts.map +1 -0
- package/dist/tooling/tool-response.js +63 -0
- package/dist/tooling/tool-response.js.map +1 -0
- package/dist/tooling/tools-registry.d.ts +5 -0
- package/dist/tooling/tools-registry.d.ts.map +1 -0
- package/dist/tooling/tools-registry.js +532 -0
- package/dist/tooling/tools-registry.js.map +1 -0
- package/dist/tools.d.ts +12 -12
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +351 -51
- package/dist/tools.js.map +1 -1
- package/package.json +7 -5
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
function isObject(value) {
|
|
2
|
+
return typeof value === 'object' && value !== null;
|
|
3
|
+
}
|
|
4
|
+
function getMethod(value) {
|
|
5
|
+
if (!isObject(value))
|
|
6
|
+
return undefined;
|
|
7
|
+
const { method } = value;
|
|
8
|
+
return typeof method === 'string' ? method : undefined;
|
|
9
|
+
}
|
|
10
|
+
function parseId(value) {
|
|
11
|
+
if (!isObject(value) || !('id' in value)) {
|
|
12
|
+
return { value: null, isValid: false };
|
|
13
|
+
}
|
|
14
|
+
const { id } = value;
|
|
15
|
+
if (typeof id === 'string' || typeof id === 'number' || id === null) {
|
|
16
|
+
return { value: id, isValid: true };
|
|
17
|
+
}
|
|
18
|
+
return { value: null, isValid: false };
|
|
19
|
+
}
|
|
20
|
+
function isRequest(value) {
|
|
21
|
+
if (!isObject(value))
|
|
22
|
+
return false;
|
|
23
|
+
const { id } = value;
|
|
24
|
+
return typeof id === 'string' || typeof id === 'number';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Strict stdio transport wrapper that:
|
|
28
|
+
* - Rejects JSON-RPC batch payloads (arrays) with a JSON-RPC error
|
|
29
|
+
* - Enforces lifecycle: `initialize` must be the first request
|
|
30
|
+
*
|
|
31
|
+
* This addresses interoperability issues where some clients send malformed input
|
|
32
|
+
* (batches) or where SDKs do not strictly enforce initialization ordering.
|
|
33
|
+
*/
|
|
34
|
+
export class StrictStdioServerTransport {
|
|
35
|
+
stdin;
|
|
36
|
+
stdout;
|
|
37
|
+
started = false;
|
|
38
|
+
buffer = '';
|
|
39
|
+
seenInitializeRequest = false;
|
|
40
|
+
onmessage;
|
|
41
|
+
onerror;
|
|
42
|
+
onclose;
|
|
43
|
+
constructor(stdin, stdout) {
|
|
44
|
+
this.stdin = stdin ?? process.stdin;
|
|
45
|
+
this.stdout = stdout ?? process.stdout;
|
|
46
|
+
}
|
|
47
|
+
start() {
|
|
48
|
+
if (this.started) {
|
|
49
|
+
throw new Error('StrictStdioServerTransport already started');
|
|
50
|
+
}
|
|
51
|
+
this.started = true;
|
|
52
|
+
this.stdin.on('data', this.onData);
|
|
53
|
+
this.stdin.on('error', this.onError);
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
}
|
|
56
|
+
close() {
|
|
57
|
+
this.stdin.off('data', this.onData);
|
|
58
|
+
this.stdin.off('error', this.onError);
|
|
59
|
+
this.buffer = '';
|
|
60
|
+
this.onclose?.();
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
}
|
|
63
|
+
async send(message) {
|
|
64
|
+
const json = `${JSON.stringify(message)}\n`;
|
|
65
|
+
await new Promise((resolve) => {
|
|
66
|
+
if (this.stdout.write(json, 'utf8')) {
|
|
67
|
+
resolve();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.stdout.once('drain', () => {
|
|
71
|
+
resolve();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
onData = (chunk) => {
|
|
77
|
+
this.buffer +=
|
|
78
|
+
typeof chunk === 'string' ? chunk : chunk.toString('utf8');
|
|
79
|
+
this.processBuffer();
|
|
80
|
+
};
|
|
81
|
+
onError = (error) => {
|
|
82
|
+
this.onerror?.(error);
|
|
83
|
+
};
|
|
84
|
+
async sendJsonRpcError(id, code, message, extra) {
|
|
85
|
+
const payload = {
|
|
86
|
+
jsonrpc: '2.0',
|
|
87
|
+
id,
|
|
88
|
+
error: {
|
|
89
|
+
code,
|
|
90
|
+
message,
|
|
91
|
+
...(extra?.data !== undefined ? { data: extra.data } : {}),
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
await this.send(payload);
|
|
96
|
+
}
|
|
97
|
+
catch (sendError) {
|
|
98
|
+
this.onerror?.(sendError instanceof Error ? sendError : new Error(String(sendError)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
processBuffer() {
|
|
102
|
+
while (this.buffer.length > 0) {
|
|
103
|
+
const newlineIndex = this.buffer.indexOf('\n');
|
|
104
|
+
if (newlineIndex < 0)
|
|
105
|
+
return;
|
|
106
|
+
const rawLine = this.buffer.slice(0, newlineIndex);
|
|
107
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
108
|
+
const line = rawLine.endsWith('\r') ? rawLine.slice(0, -1) : rawLine;
|
|
109
|
+
if (line.trim().length === 0)
|
|
110
|
+
continue;
|
|
111
|
+
void this.processLine(line);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async processLine(line) {
|
|
115
|
+
let parsed;
|
|
116
|
+
try {
|
|
117
|
+
parsed = JSON.parse(line);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
+
await this.sendJsonRpcError(null, -32700, 'Parse error', { data: message });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await this.handleIncomingMessage(parsed);
|
|
125
|
+
}
|
|
126
|
+
async handleIncomingMessage(message) {
|
|
127
|
+
// JSON-RPC batching is not supported in MCP 2025-06-18+.
|
|
128
|
+
if (Array.isArray(message)) {
|
|
129
|
+
await this.sendJsonRpcError(null, -32600, 'Invalid Request');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (!isObject(message)) {
|
|
133
|
+
await this.sendJsonRpcError(null, -32600, 'Invalid Request');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const method = getMethod(message);
|
|
137
|
+
if (!method) {
|
|
138
|
+
await this.sendJsonRpcError(parseId(message).value, -32600, 'Invalid Request');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!this.seenInitializeRequest) {
|
|
142
|
+
if (method !== 'initialize') {
|
|
143
|
+
if (isRequest(message)) {
|
|
144
|
+
const { value: id } = parseId(message);
|
|
145
|
+
const responseId = typeof id === 'string' || typeof id === 'number' ? id : null;
|
|
146
|
+
await this.sendJsonRpcError(responseId, -32000, 'Bad Request: Server not initialized');
|
|
147
|
+
}
|
|
148
|
+
// For notifications before initialize, we cannot respond; ignore.
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// `initialize` must be first; mark after we accept it.
|
|
152
|
+
this.seenInitializeRequest = true;
|
|
153
|
+
}
|
|
154
|
+
// Forward valid messages to the SDK server.
|
|
155
|
+
this.onmessage?.(message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=strict-stdio-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict-stdio-transport.js","sourceRoot":"","sources":["../../src/lib/strict-stdio-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { ResourceStore } from './lib/resource-store.js';
|
|
3
|
+
export declare function registerInstructionResource(server: McpServer, instructions: string): void;
|
|
4
|
+
export declare function registerResultResources(server: McpServer, store: ResourceStore): void;
|
|
5
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAM7D,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,MAAM,GACnB,IAAI,CAmBN;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,aAAa,GACnB,IAAI,CA6BN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { ErrorCode, McpError } from './lib/errors.js';
|
|
3
|
+
const RESULT_TEMPLATE = new ResourceTemplate('fs-context://result/{id}', {
|
|
4
|
+
list: undefined,
|
|
5
|
+
});
|
|
6
|
+
export function registerInstructionResource(server, instructions) {
|
|
7
|
+
server.registerResource('fs-context-instructions', 'internal://instructions', {
|
|
8
|
+
title: 'Server Instructions',
|
|
9
|
+
description: 'Guidance for using the fs-context MCP tools effectively.',
|
|
10
|
+
mimeType: 'text/markdown',
|
|
11
|
+
}, (uri) => ({
|
|
12
|
+
contents: [
|
|
13
|
+
{
|
|
14
|
+
uri: uri.href,
|
|
15
|
+
mimeType: 'text/markdown',
|
|
16
|
+
text: instructions,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
export function registerResultResources(server, store) {
|
|
22
|
+
server.registerResource('fs-context-result', RESULT_TEMPLATE, {
|
|
23
|
+
title: 'Cached Tool Result',
|
|
24
|
+
description: 'Ephemeral cached tool output exposed as an MCP resource. Not guaranteed to be listed via resources/list.',
|
|
25
|
+
mimeType: 'text/plain',
|
|
26
|
+
}, (uri, variables) => {
|
|
27
|
+
const { id } = variables;
|
|
28
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
29
|
+
throw new McpError(ErrorCode.E_INVALID_INPUT, 'Missing resource id');
|
|
30
|
+
}
|
|
31
|
+
const entry = store.getText(uri.toString());
|
|
32
|
+
return {
|
|
33
|
+
contents: [
|
|
34
|
+
{
|
|
35
|
+
uri: entry.uri,
|
|
36
|
+
mimeType: entry.mimeType,
|
|
37
|
+
text: entry.text,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAG3E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,eAAe,GAAG,IAAI,gBAAgB,CAAC,0BAA0B,EAAE;IACvE,IAAI,EAAE,SAAS;CAChB,CAAC,CAAC;AAEH,MAAM,UAAU,2BAA2B,CACzC,MAAiB,EACjB,YAAoB;IAEpB,MAAM,CAAC,gBAAgB,CACrB,yBAAyB,EACzB,yBAAyB,EACzB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,0DAA0D;QACvE,QAAQ,EAAE,eAAe;KAC1B,EACD,CAAC,GAAG,EAAsB,EAAE,CAAC,CAAC;QAC5B,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,GAAG,CAAC,IAAI;gBACb,QAAQ,EAAE,eAAe;gBACzB,IAAI,EAAE,YAAY;aACnB;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,KAAoB;IAEpB,MAAM,CAAC,gBAAgB,CACrB,mBAAmB,EACnB,eAAe,EACf;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EACT,0GAA0G;QAC5G,QAAQ,EAAE,YAAY;KACvB,EACD,CAAC,GAAG,EAAE,SAAS,EAAsB,EAAE;QACrC,MAAM,EAAE,EAAE,EAAE,GAAG,SAAS,CAAC;QACzB,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE5C,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,KAAK,CAAC,GAAG;oBACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,IAAI,EAAE,KAAK,CAAC,IAAI;iBACjB;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/schemas.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
declare const TreeEntryTypeSchema: z.ZodEnum<{
|
|
3
|
+
file: "file";
|
|
4
|
+
directory: "directory";
|
|
5
|
+
symlink: "symlink";
|
|
6
|
+
other: "other";
|
|
7
|
+
}>;
|
|
8
|
+
interface TreeEntry {
|
|
9
|
+
name: string;
|
|
10
|
+
type: z.infer<typeof TreeEntryTypeSchema>;
|
|
11
|
+
relativePath: string;
|
|
12
|
+
children?: TreeEntry[] | undefined;
|
|
13
|
+
}
|
|
2
14
|
export declare const ListDirectoryInputSchema: z.ZodObject<{
|
|
3
15
|
path: z.ZodOptional<z.ZodString>;
|
|
4
16
|
includeHidden: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -10,6 +22,13 @@ export declare const SearchFilesInputSchema: z.ZodObject<{
|
|
|
10
22
|
maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
23
|
includeIgnored: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
24
|
}, z.core.$strict>;
|
|
25
|
+
export declare const TreeInputSchema: z.ZodObject<{
|
|
26
|
+
path: z.ZodOptional<z.ZodString>;
|
|
27
|
+
maxDepth: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
28
|
+
maxEntries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
29
|
+
includeHidden: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
30
|
+
includeIgnored: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
31
|
+
}, z.core.$strict>;
|
|
13
32
|
export declare const SearchContentInputSchema: z.ZodObject<{
|
|
14
33
|
path: z.ZodOptional<z.ZodString>;
|
|
15
34
|
pattern: z.ZodString;
|
|
@@ -18,10 +37,14 @@ export declare const SearchContentInputSchema: z.ZodObject<{
|
|
|
18
37
|
export declare const ReadFileInputSchema: z.ZodObject<{
|
|
19
38
|
path: z.ZodString;
|
|
20
39
|
head: z.ZodOptional<z.ZodInt>;
|
|
40
|
+
startLine: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
21
42
|
}, z.core.$strict>;
|
|
22
43
|
export declare const ReadMultipleFilesInputSchema: z.ZodObject<{
|
|
23
44
|
paths: z.ZodArray<z.ZodString>;
|
|
24
45
|
head: z.ZodOptional<z.ZodInt>;
|
|
46
|
+
startLine: z.ZodOptional<z.ZodNumber>;
|
|
47
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
25
48
|
}, z.core.$strict>;
|
|
26
49
|
export declare const GetFileInfoInputSchema: z.ZodObject<{
|
|
27
50
|
path: z.ZodString;
|
|
@@ -63,32 +86,49 @@ export declare const ListDirectoryOutputSchema: z.ZodObject<{
|
|
|
63
86
|
}, z.core.$strip>>;
|
|
64
87
|
}, z.core.$strip>;
|
|
65
88
|
export declare const SearchFilesOutputSchema: z.ZodObject<{
|
|
89
|
+
totalMatches: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
91
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
92
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
93
|
+
code: z.ZodString;
|
|
94
|
+
message: z.ZodString;
|
|
95
|
+
path: z.ZodOptional<z.ZodString>;
|
|
96
|
+
suggestion: z.ZodOptional<z.ZodString>;
|
|
97
|
+
}, z.core.$strip>>;
|
|
66
98
|
ok: z.ZodBoolean;
|
|
67
99
|
results: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
68
100
|
path: z.ZodString;
|
|
69
101
|
size: z.ZodOptional<z.ZodNumber>;
|
|
70
102
|
modified: z.ZodOptional<z.ZodString>;
|
|
71
103
|
}, z.core.$strip>>>;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
export declare const SearchContentOutputSchema: z.ZodObject<{
|
|
72
106
|
totalMatches: z.ZodOptional<z.ZodNumber>;
|
|
73
107
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
108
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
74
109
|
error: z.ZodOptional<z.ZodObject<{
|
|
75
110
|
code: z.ZodString;
|
|
76
111
|
message: z.ZodString;
|
|
77
112
|
path: z.ZodOptional<z.ZodString>;
|
|
78
113
|
suggestion: z.ZodOptional<z.ZodString>;
|
|
79
114
|
}, z.core.$strip>>;
|
|
80
|
-
}, z.core.$strip>;
|
|
81
|
-
export declare const SearchContentOutputSchema: z.ZodObject<{
|
|
82
115
|
ok: z.ZodBoolean;
|
|
83
116
|
matches: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
84
117
|
file: z.ZodString;
|
|
85
118
|
line: z.ZodNumber;
|
|
86
119
|
content: z.ZodString;
|
|
120
|
+
matchCount: z.ZodNumber;
|
|
87
121
|
contextBefore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
88
122
|
contextAfter: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
89
123
|
}, z.core.$strip>>>;
|
|
90
|
-
|
|
124
|
+
}, z.core.$strip>;
|
|
125
|
+
export declare const TreeOutputSchema: z.ZodObject<{
|
|
126
|
+
ok: z.ZodBoolean;
|
|
127
|
+
root: z.ZodOptional<z.ZodString>;
|
|
128
|
+
tree: z.ZodOptional<z.ZodType<TreeEntry, unknown, z.core.$ZodTypeInternals<TreeEntry, unknown>>>;
|
|
129
|
+
ascii: z.ZodOptional<z.ZodString>;
|
|
91
130
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
131
|
+
totalEntries: z.ZodOptional<z.ZodNumber>;
|
|
92
132
|
error: z.ZodOptional<z.ZodObject<{
|
|
93
133
|
code: z.ZodString;
|
|
94
134
|
message: z.ZodString;
|
|
@@ -97,11 +137,22 @@ export declare const SearchContentOutputSchema: z.ZodObject<{
|
|
|
97
137
|
}, z.core.$strip>>;
|
|
98
138
|
}, z.core.$strip>;
|
|
99
139
|
export declare const ReadFileOutputSchema: z.ZodObject<{
|
|
100
|
-
ok: z.ZodBoolean;
|
|
101
|
-
path: z.ZodOptional<z.ZodString>;
|
|
102
140
|
content: z.ZodOptional<z.ZodString>;
|
|
103
141
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
142
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
104
143
|
totalLines: z.ZodOptional<z.ZodNumber>;
|
|
144
|
+
readMode: z.ZodOptional<z.ZodEnum<{
|
|
145
|
+
head: "head";
|
|
146
|
+
full: "full";
|
|
147
|
+
range: "range";
|
|
148
|
+
}>>;
|
|
149
|
+
head: z.ZodOptional<z.ZodNumber>;
|
|
150
|
+
startLine: z.ZodOptional<z.ZodNumber>;
|
|
151
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
152
|
+
linesRead: z.ZodOptional<z.ZodNumber>;
|
|
153
|
+
hasMoreLines: z.ZodOptional<z.ZodBoolean>;
|
|
154
|
+
ok: z.ZodBoolean;
|
|
155
|
+
path: z.ZodOptional<z.ZodString>;
|
|
105
156
|
error: z.ZodOptional<z.ZodObject<{
|
|
106
157
|
code: z.ZodString;
|
|
107
158
|
message: z.ZodString;
|
|
@@ -112,9 +163,21 @@ export declare const ReadFileOutputSchema: z.ZodObject<{
|
|
|
112
163
|
export declare const ReadMultipleFilesOutputSchema: z.ZodObject<{
|
|
113
164
|
ok: z.ZodBoolean;
|
|
114
165
|
results: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
115
|
-
path: z.ZodString;
|
|
116
166
|
content: z.ZodOptional<z.ZodString>;
|
|
117
167
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
168
|
+
resourceUri: z.ZodOptional<z.ZodString>;
|
|
169
|
+
totalLines: z.ZodOptional<z.ZodNumber>;
|
|
170
|
+
readMode: z.ZodOptional<z.ZodEnum<{
|
|
171
|
+
head: "head";
|
|
172
|
+
full: "full";
|
|
173
|
+
range: "range";
|
|
174
|
+
}>>;
|
|
175
|
+
head: z.ZodOptional<z.ZodNumber>;
|
|
176
|
+
startLine: z.ZodOptional<z.ZodNumber>;
|
|
177
|
+
endLine: z.ZodOptional<z.ZodNumber>;
|
|
178
|
+
linesRead: z.ZodOptional<z.ZodNumber>;
|
|
179
|
+
hasMoreLines: z.ZodOptional<z.ZodBoolean>;
|
|
180
|
+
path: z.ZodString;
|
|
118
181
|
error: z.ZodOptional<z.ZodString>;
|
|
119
182
|
}, z.core.$strip>>>;
|
|
120
183
|
summary: z.ZodOptional<z.ZodObject<{
|
|
@@ -141,11 +204,12 @@ export declare const GetFileInfoOutputSchema: z.ZodObject<{
|
|
|
141
204
|
other: "other";
|
|
142
205
|
}>;
|
|
143
206
|
size: z.ZodNumber;
|
|
144
|
-
|
|
207
|
+
tokenEstimate: z.ZodOptional<z.ZodNumber>;
|
|
208
|
+
created: z.ZodString;
|
|
145
209
|
modified: z.ZodString;
|
|
146
|
-
accessed: z.
|
|
210
|
+
accessed: z.ZodString;
|
|
147
211
|
permissions: z.ZodString;
|
|
148
|
-
isHidden: z.
|
|
212
|
+
isHidden: z.ZodBoolean;
|
|
149
213
|
mimeType: z.ZodOptional<z.ZodString>;
|
|
150
214
|
symlinkTarget: z.ZodOptional<z.ZodString>;
|
|
151
215
|
}, z.core.$strip>>;
|
|
@@ -170,11 +234,12 @@ export declare const GetMultipleFileInfoOutputSchema: z.ZodObject<{
|
|
|
170
234
|
other: "other";
|
|
171
235
|
}>;
|
|
172
236
|
size: z.ZodNumber;
|
|
173
|
-
|
|
237
|
+
tokenEstimate: z.ZodOptional<z.ZodNumber>;
|
|
238
|
+
created: z.ZodString;
|
|
174
239
|
modified: z.ZodString;
|
|
175
|
-
accessed: z.
|
|
240
|
+
accessed: z.ZodString;
|
|
176
241
|
permissions: z.ZodString;
|
|
177
|
-
isHidden: z.
|
|
242
|
+
isHidden: z.ZodBoolean;
|
|
178
243
|
mimeType: z.ZodOptional<z.ZodString>;
|
|
179
244
|
symlinkTarget: z.ZodOptional<z.ZodString>;
|
|
180
245
|
}, z.core.$strip>>;
|
|
@@ -192,4 +257,5 @@ export declare const GetMultipleFileInfoOutputSchema: z.ZodObject<{
|
|
|
192
257
|
suggestion: z.ZodOptional<z.ZodString>;
|
|
193
258
|
}, z.core.$strip>>;
|
|
194
259
|
}, z.core.$strip>;
|
|
260
|
+
export {};
|
|
195
261
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB,QAAA,MAAM,mBAAmB;;;;;EAAoD,CAAC;AAE9E,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;CACpC;AAuGD,eAAO,MAAM,wBAAwB;;;kBAanC,CAAC;AAEH,eAAO,MAAM,iCAAiC,iCAEX,CAAC;AAEpC,eAAO,MAAM,sBAAsB;;;;;kBA+CjC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;kBAoC1B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;kBAoBnC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;kBAiBC,CAAC;AAElC,eAAO,MAAM,4BAA4B;;;;;kBAgBR,CAAC;AAElC,eAAO,MAAM,sBAAsB;;kBAQjC,CAAC;AAEH,eAAO,MAAM,8BAA8B;;kBASzC,CAAC;AAEH,eAAO,MAAM,kCAAkC;;;;;;;;;iBAI7C,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;iBAgBpC,CAAC;AASH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;iBAWlC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;iBAcpC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;iBAQ3B,CAAC;AAeH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;iBAI/B,CAAC;AAOH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKxC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIlC,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAa1C,CAAC"}
|
package/dist/schemas.js
CHANGED
|
@@ -12,6 +12,13 @@ function isSafeGlobPattern(value) {
|
|
|
12
12
|
return true;
|
|
13
13
|
}
|
|
14
14
|
const FileTypeSchema = z.enum(['file', 'directory', 'symlink', 'other']);
|
|
15
|
+
const TreeEntryTypeSchema = z.enum(['file', 'directory', 'symlink', 'other']);
|
|
16
|
+
const TreeEntrySchema = z.lazy(() => z.object({
|
|
17
|
+
name: z.string(),
|
|
18
|
+
type: TreeEntryTypeSchema,
|
|
19
|
+
relativePath: z.string(),
|
|
20
|
+
children: z.array(TreeEntrySchema).optional(),
|
|
21
|
+
}));
|
|
15
22
|
const ErrorSchema = z.object({
|
|
16
23
|
code: z.string().describe('Error code (e.g., E_NOT_FOUND)'),
|
|
17
24
|
message: z.string().describe('Human-readable error message'),
|
|
@@ -24,16 +31,52 @@ const HeadLinesSchema = z
|
|
|
24
31
|
.max(100000, 'head cannot exceed 100,000 lines')
|
|
25
32
|
.optional()
|
|
26
33
|
.describe('Read only the first N lines');
|
|
34
|
+
const LineNumberSchema = z
|
|
35
|
+
.number()
|
|
36
|
+
.int({ error: 'line numbers must be integers' })
|
|
37
|
+
.min(1, 'line numbers must be at least 1');
|
|
38
|
+
const validateReadRange = (value, ctx) => {
|
|
39
|
+
const hasHead = value.head !== undefined;
|
|
40
|
+
const hasStart = value.startLine !== undefined;
|
|
41
|
+
const hasEnd = value.endLine !== undefined;
|
|
42
|
+
if (hasHead && (hasStart || hasEnd)) {
|
|
43
|
+
ctx.addIssue({
|
|
44
|
+
code: 'custom',
|
|
45
|
+
path: ['head'],
|
|
46
|
+
message: 'head cannot be used together with startLine/endLine',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (hasEnd && !hasStart) {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: 'custom',
|
|
52
|
+
path: ['endLine'],
|
|
53
|
+
message: 'endLine requires startLine',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (value.startLine !== undefined &&
|
|
57
|
+
value.endLine !== undefined &&
|
|
58
|
+
value.endLine < value.startLine) {
|
|
59
|
+
ctx.addIssue({
|
|
60
|
+
code: 'custom',
|
|
61
|
+
path: ['endLine'],
|
|
62
|
+
message: 'endLine must be greater than or equal to startLine',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
27
66
|
const FileInfoSchema = z.object({
|
|
28
67
|
name: z.string(),
|
|
29
68
|
path: z.string(),
|
|
30
69
|
type: FileTypeSchema,
|
|
31
70
|
size: z.number(),
|
|
32
|
-
|
|
71
|
+
tokenEstimate: z
|
|
72
|
+
.number()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe('Approximate token count estimate (rule of thumb: ceil(size/4))'),
|
|
75
|
+
created: z.string(),
|
|
33
76
|
modified: z.string(),
|
|
34
|
-
accessed: z.string()
|
|
77
|
+
accessed: z.string(),
|
|
35
78
|
permissions: z.string(),
|
|
36
|
-
isHidden: z.boolean()
|
|
79
|
+
isHidden: z.boolean(),
|
|
37
80
|
mimeType: z.string().optional(),
|
|
38
81
|
symlinkTarget: z.string().optional(),
|
|
39
82
|
});
|
|
@@ -42,6 +85,11 @@ const OperationSummarySchema = z.object({
|
|
|
42
85
|
succeeded: z.number(),
|
|
43
86
|
failed: z.number(),
|
|
44
87
|
});
|
|
88
|
+
const ReadRangeInputSchema = z.strictObject({
|
|
89
|
+
head: HeadLinesSchema,
|
|
90
|
+
startLine: LineNumberSchema.optional(),
|
|
91
|
+
endLine: LineNumberSchema.optional(),
|
|
92
|
+
});
|
|
45
93
|
export const ListDirectoryInputSchema = z.strictObject({
|
|
46
94
|
path: z
|
|
47
95
|
.string()
|
|
@@ -96,6 +144,39 @@ export const SearchFilesInputSchema = z.strictObject({
|
|
|
96
144
|
.describe('Include normally ignored directories (node_modules, dist, .git, etc). ' +
|
|
97
145
|
'Set to true when debugging in dependencies.'),
|
|
98
146
|
});
|
|
147
|
+
export const TreeInputSchema = z.strictObject({
|
|
148
|
+
path: z
|
|
149
|
+
.string()
|
|
150
|
+
.optional()
|
|
151
|
+
.describe('Base directory to render as a tree (leave empty for workspace root). Examples: "src", "lib"'),
|
|
152
|
+
maxDepth: z
|
|
153
|
+
.number()
|
|
154
|
+
.int({ error: 'maxDepth must be an integer' })
|
|
155
|
+
.min(0, 'maxDepth must be at least 0')
|
|
156
|
+
.max(50, 'maxDepth cannot exceed 50')
|
|
157
|
+
.optional()
|
|
158
|
+
.default(5)
|
|
159
|
+
.describe('Maximum depth to recurse (0 = just the root)'),
|
|
160
|
+
maxEntries: z
|
|
161
|
+
.number()
|
|
162
|
+
.int({ error: 'maxEntries must be an integer' })
|
|
163
|
+
.min(1, 'maxEntries must be at least 1')
|
|
164
|
+
.max(20000, 'maxEntries cannot exceed 20,000')
|
|
165
|
+
.optional()
|
|
166
|
+
.default(1000)
|
|
167
|
+
.describe('Maximum number of entries to return before truncating'),
|
|
168
|
+
includeHidden: z
|
|
169
|
+
.boolean()
|
|
170
|
+
.optional()
|
|
171
|
+
.default(false)
|
|
172
|
+
.describe('Include hidden files and directories'),
|
|
173
|
+
includeIgnored: z
|
|
174
|
+
.boolean()
|
|
175
|
+
.optional()
|
|
176
|
+
.default(false)
|
|
177
|
+
.describe('Include normally ignored directories (node_modules, dist, .git, etc). ' +
|
|
178
|
+
'When true, also disables root .gitignore filtering.'),
|
|
179
|
+
});
|
|
99
180
|
export const SearchContentInputSchema = z.strictObject({
|
|
100
181
|
path: z
|
|
101
182
|
.string()
|
|
@@ -113,15 +194,17 @@ export const SearchContentInputSchema = z.strictObject({
|
|
|
113
194
|
.default(false)
|
|
114
195
|
.describe('Include hidden files and directories'),
|
|
115
196
|
});
|
|
116
|
-
export const ReadFileInputSchema =
|
|
197
|
+
export const ReadFileInputSchema = ReadRangeInputSchema.extend({
|
|
117
198
|
path: z
|
|
118
199
|
.string()
|
|
119
200
|
.min(1, 'Path cannot be empty')
|
|
120
201
|
.describe('Path to the file to read. ' +
|
|
121
202
|
'Examples: "README.md", "src/index.ts", "package.json"'),
|
|
122
203
|
head: HeadLinesSchema.describe('Read only the first N lines of the file (useful for previewing large files)'),
|
|
123
|
-
|
|
124
|
-
|
|
204
|
+
startLine: LineNumberSchema.optional().describe('1-based line number to start reading from (inclusive). Useful for reading context around a match.'),
|
|
205
|
+
endLine: LineNumberSchema.optional().describe('1-based line number to stop reading at (inclusive). Requires startLine.'),
|
|
206
|
+
}).superRefine(validateReadRange);
|
|
207
|
+
export const ReadMultipleFilesInputSchema = ReadRangeInputSchema.extend({
|
|
125
208
|
paths: z
|
|
126
209
|
.array(z.string().min(1, 'Path cannot be empty'))
|
|
127
210
|
.min(1, 'At least one path is required')
|
|
@@ -129,7 +212,9 @@ export const ReadMultipleFilesInputSchema = z.strictObject({
|
|
|
129
212
|
.describe('Array of file paths to read. ' +
|
|
130
213
|
'Examples: ["README.md", "package.json"], ["src/index.ts", "src/server.ts"]'),
|
|
131
214
|
head: HeadLinesSchema.describe('Read only the first N lines of each file'),
|
|
132
|
-
|
|
215
|
+
startLine: LineNumberSchema.optional().describe('1-based line number to start reading from (inclusive), applied to each file.'),
|
|
216
|
+
endLine: LineNumberSchema.optional().describe('1-based line number to stop reading at (inclusive), applied to each file. Requires startLine.'),
|
|
217
|
+
}).superRefine(validateReadRange);
|
|
133
218
|
export const GetFileInfoInputSchema = z.strictObject({
|
|
134
219
|
path: z
|
|
135
220
|
.string()
|
|
@@ -165,7 +250,13 @@ export const ListDirectoryOutputSchema = z.object({
|
|
|
165
250
|
totalEntries: z.number().optional(),
|
|
166
251
|
error: ErrorSchema.optional(),
|
|
167
252
|
});
|
|
168
|
-
|
|
253
|
+
const SearchSummarySchema = z.object({
|
|
254
|
+
totalMatches: z.number().optional(),
|
|
255
|
+
truncated: z.boolean().optional(),
|
|
256
|
+
resourceUri: z.string().optional(),
|
|
257
|
+
error: ErrorSchema.optional(),
|
|
258
|
+
});
|
|
259
|
+
export const SearchFilesOutputSchema = SearchSummarySchema.extend({
|
|
169
260
|
ok: z.boolean(),
|
|
170
261
|
results: z
|
|
171
262
|
.array(z.object({
|
|
@@ -174,43 +265,53 @@ export const SearchFilesOutputSchema = z.object({
|
|
|
174
265
|
modified: z.string().optional(),
|
|
175
266
|
}))
|
|
176
267
|
.optional(),
|
|
177
|
-
totalMatches: z.number().optional(),
|
|
178
|
-
truncated: z.boolean().optional(),
|
|
179
|
-
error: ErrorSchema.optional(),
|
|
180
268
|
});
|
|
181
|
-
export const SearchContentOutputSchema =
|
|
269
|
+
export const SearchContentOutputSchema = SearchSummarySchema.extend({
|
|
182
270
|
ok: z.boolean(),
|
|
183
271
|
matches: z
|
|
184
272
|
.array(z.object({
|
|
185
273
|
file: z.string().describe('Relative path from search base'),
|
|
186
274
|
line: z.number(),
|
|
187
275
|
content: z.string(),
|
|
276
|
+
matchCount: z.number(),
|
|
188
277
|
contextBefore: z.array(z.string()).optional(),
|
|
189
278
|
contextAfter: z.array(z.string()).optional(),
|
|
190
279
|
}))
|
|
191
280
|
.optional(),
|
|
192
|
-
|
|
281
|
+
});
|
|
282
|
+
export const TreeOutputSchema = z.object({
|
|
283
|
+
ok: z.boolean(),
|
|
284
|
+
root: z.string().optional(),
|
|
285
|
+
tree: TreeEntrySchema.optional(),
|
|
286
|
+
ascii: z.string().optional(),
|
|
193
287
|
truncated: z.boolean().optional(),
|
|
288
|
+
totalEntries: z.number().optional(),
|
|
194
289
|
error: ErrorSchema.optional(),
|
|
195
290
|
});
|
|
196
|
-
|
|
197
|
-
ok: z.boolean(),
|
|
198
|
-
path: z.string().optional(),
|
|
291
|
+
const ReadResultSchema = z.object({
|
|
199
292
|
content: z.string().optional(),
|
|
200
293
|
truncated: z.boolean().optional(),
|
|
294
|
+
resourceUri: z.string().optional(),
|
|
201
295
|
totalLines: z.number().optional(),
|
|
296
|
+
readMode: z.enum(['full', 'head', 'range']).optional(),
|
|
297
|
+
head: z.number().optional(),
|
|
298
|
+
startLine: z.number().optional(),
|
|
299
|
+
endLine: z.number().optional(),
|
|
300
|
+
linesRead: z.number().optional(),
|
|
301
|
+
hasMoreLines: z.boolean().optional(),
|
|
302
|
+
});
|
|
303
|
+
export const ReadFileOutputSchema = ReadResultSchema.extend({
|
|
304
|
+
ok: z.boolean(),
|
|
305
|
+
path: z.string().optional(),
|
|
202
306
|
error: ErrorSchema.optional(),
|
|
203
307
|
});
|
|
308
|
+
const ReadMultipleFileResultSchema = ReadResultSchema.extend({
|
|
309
|
+
path: z.string(),
|
|
310
|
+
error: z.string().optional(),
|
|
311
|
+
});
|
|
204
312
|
export const ReadMultipleFilesOutputSchema = z.object({
|
|
205
313
|
ok: z.boolean(),
|
|
206
|
-
results: z
|
|
207
|
-
.array(z.object({
|
|
208
|
-
path: z.string(),
|
|
209
|
-
content: z.string().optional(),
|
|
210
|
-
truncated: z.boolean().optional(),
|
|
211
|
-
error: z.string().optional(),
|
|
212
|
-
}))
|
|
213
|
-
.optional(),
|
|
314
|
+
results: z.array(ReadMultipleFileResultSchema).optional(),
|
|
214
315
|
summary: OperationSummarySchema.optional(),
|
|
215
316
|
error: ErrorSchema.optional(),
|
|
216
317
|
});
|