@wonderwhy-er/desktop-commander 0.2.22 → 0.2.24
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 +14 -55
- package/dist/custom-stdio.d.ts +1 -0
- package/dist/custom-stdio.js +19 -0
- package/dist/handlers/filesystem-handlers.d.ts +4 -0
- package/dist/handlers/filesystem-handlers.js +120 -14
- package/dist/handlers/node-handlers.d.ts +6 -0
- package/dist/handlers/node-handlers.js +73 -0
- package/dist/index.js +5 -3
- package/dist/search-manager.d.ts +25 -0
- package/dist/search-manager.js +212 -0
- package/dist/server.js +161 -107
- package/dist/terminal-manager.d.ts +56 -2
- package/dist/terminal-manager.js +169 -13
- package/dist/tools/edit.d.ts +28 -4
- package/dist/tools/edit.js +87 -4
- package/dist/tools/filesystem.d.ts +23 -12
- package/dist/tools/filesystem.js +201 -416
- package/dist/tools/improved-process-tools.d.ts +2 -2
- package/dist/tools/improved-process-tools.js +244 -214
- package/dist/tools/mime-types.d.ts +1 -0
- package/dist/tools/mime-types.js +7 -0
- package/dist/tools/pdf/extract-images.d.ts +34 -0
- package/dist/tools/pdf/extract-images.js +132 -0
- package/dist/tools/pdf/index.d.ts +6 -0
- package/dist/tools/pdf/index.js +3 -0
- package/dist/tools/pdf/lib/pdf2md.d.ts +36 -0
- package/dist/tools/pdf/lib/pdf2md.js +76 -0
- package/dist/tools/pdf/manipulations.d.ts +13 -0
- package/dist/tools/pdf/manipulations.js +96 -0
- package/dist/tools/pdf/markdown.d.ts +7 -0
- package/dist/tools/pdf/markdown.js +37 -0
- package/dist/tools/pdf/utils.d.ts +12 -0
- package/dist/tools/pdf/utils.js +34 -0
- package/dist/tools/prompts.js +0 -10
- package/dist/tools/schemas.d.ts +167 -12
- package/dist/tools/schemas.js +54 -5
- package/dist/types.d.ts +2 -1
- package/dist/utils/feature-flags.js +7 -4
- package/dist/utils/files/base.d.ts +167 -0
- package/dist/utils/files/base.js +5 -0
- package/dist/utils/files/binary.d.ts +21 -0
- package/dist/utils/files/binary.js +65 -0
- package/dist/utils/files/excel.d.ts +24 -0
- package/dist/utils/files/excel.js +416 -0
- package/dist/utils/files/factory.d.ts +40 -0
- package/dist/utils/files/factory.js +101 -0
- package/dist/utils/files/image.d.ts +21 -0
- package/dist/utils/files/image.js +78 -0
- package/dist/utils/files/index.d.ts +10 -0
- package/dist/utils/files/index.js +13 -0
- package/dist/utils/files/pdf.d.ts +32 -0
- package/dist/utils/files/pdf.js +142 -0
- package/dist/utils/files/text.d.ts +63 -0
- package/dist/utils/files/text.js +357 -0
- package/dist/utils/ripgrep-resolver.js +3 -2
- package/dist/utils/system-info.d.ts +5 -0
- package/dist/utils/system-info.js +71 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -3
package/dist/tools/schemas.d.ts
CHANGED
|
@@ -30,15 +30,21 @@ export declare const StartProcessArgsSchema: z.ZodObject<{
|
|
|
30
30
|
export declare const ReadProcessOutputArgsSchema: z.ZodObject<{
|
|
31
31
|
pid: z.ZodNumber;
|
|
32
32
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
33
35
|
verbose_timing: z.ZodOptional<z.ZodBoolean>;
|
|
34
36
|
}, "strip", z.ZodTypeAny, {
|
|
35
37
|
pid: number;
|
|
38
|
+
length?: number | undefined;
|
|
36
39
|
timeout_ms?: number | undefined;
|
|
37
40
|
verbose_timing?: boolean | undefined;
|
|
41
|
+
offset?: number | undefined;
|
|
38
42
|
}, {
|
|
39
43
|
pid: number;
|
|
44
|
+
length?: number | undefined;
|
|
40
45
|
timeout_ms?: number | undefined;
|
|
41
46
|
verbose_timing?: boolean | undefined;
|
|
47
|
+
offset?: number | undefined;
|
|
42
48
|
}>;
|
|
43
49
|
export declare const ForceTerminateArgsSchema: z.ZodObject<{
|
|
44
50
|
pid: z.ZodNumber;
|
|
@@ -60,16 +66,25 @@ export declare const ReadFileArgsSchema: z.ZodObject<{
|
|
|
60
66
|
isUrl: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
61
67
|
offset: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
62
68
|
length: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
69
|
+
sheet: z.ZodOptional<z.ZodString>;
|
|
70
|
+
range: z.ZodOptional<z.ZodString>;
|
|
71
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
63
72
|
}, "strip", z.ZodTypeAny, {
|
|
64
73
|
length: number;
|
|
65
74
|
path: string;
|
|
66
|
-
isUrl: boolean;
|
|
67
75
|
offset: number;
|
|
76
|
+
isUrl: boolean;
|
|
77
|
+
options?: Record<string, any> | undefined;
|
|
78
|
+
sheet?: string | undefined;
|
|
79
|
+
range?: string | undefined;
|
|
68
80
|
}, {
|
|
69
81
|
path: string;
|
|
70
82
|
length?: number | undefined;
|
|
71
|
-
|
|
83
|
+
options?: Record<string, any> | undefined;
|
|
72
84
|
offset?: number | undefined;
|
|
85
|
+
isUrl?: boolean | undefined;
|
|
86
|
+
sheet?: string | undefined;
|
|
87
|
+
range?: string | undefined;
|
|
73
88
|
}>;
|
|
74
89
|
export declare const ReadMultipleFilesArgsSchema: z.ZodObject<{
|
|
75
90
|
paths: z.ZodArray<z.ZodString, "many">;
|
|
@@ -91,6 +106,124 @@ export declare const WriteFileArgsSchema: z.ZodObject<{
|
|
|
91
106
|
content: string;
|
|
92
107
|
mode?: "rewrite" | "append" | undefined;
|
|
93
108
|
}>;
|
|
109
|
+
export declare const PdfInsertOperationSchema: z.ZodObject<{
|
|
110
|
+
type: z.ZodLiteral<"insert">;
|
|
111
|
+
pageIndex: z.ZodNumber;
|
|
112
|
+
markdown: z.ZodOptional<z.ZodString>;
|
|
113
|
+
sourcePdfPath: z.ZodOptional<z.ZodString>;
|
|
114
|
+
pdfOptions: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
type: "insert";
|
|
117
|
+
pageIndex: number;
|
|
118
|
+
markdown?: string | undefined;
|
|
119
|
+
sourcePdfPath?: string | undefined;
|
|
120
|
+
pdfOptions?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
121
|
+
}, {
|
|
122
|
+
type: "insert";
|
|
123
|
+
pageIndex: number;
|
|
124
|
+
markdown?: string | undefined;
|
|
125
|
+
sourcePdfPath?: string | undefined;
|
|
126
|
+
pdfOptions?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
127
|
+
}>;
|
|
128
|
+
export declare const PdfDeleteOperationSchema: z.ZodObject<{
|
|
129
|
+
type: z.ZodLiteral<"delete">;
|
|
130
|
+
pageIndexes: z.ZodArray<z.ZodNumber, "many">;
|
|
131
|
+
}, "strip", z.ZodTypeAny, {
|
|
132
|
+
type: "delete";
|
|
133
|
+
pageIndexes: number[];
|
|
134
|
+
}, {
|
|
135
|
+
type: "delete";
|
|
136
|
+
pageIndexes: number[];
|
|
137
|
+
}>;
|
|
138
|
+
export declare const PdfOperationSchema: z.ZodUnion<[z.ZodObject<{
|
|
139
|
+
type: z.ZodLiteral<"insert">;
|
|
140
|
+
pageIndex: z.ZodNumber;
|
|
141
|
+
markdown: z.ZodOptional<z.ZodString>;
|
|
142
|
+
sourcePdfPath: z.ZodOptional<z.ZodString>;
|
|
143
|
+
pdfOptions: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
|
|
144
|
+
}, "strip", z.ZodTypeAny, {
|
|
145
|
+
type: "insert";
|
|
146
|
+
pageIndex: number;
|
|
147
|
+
markdown?: string | undefined;
|
|
148
|
+
sourcePdfPath?: string | undefined;
|
|
149
|
+
pdfOptions?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
150
|
+
}, {
|
|
151
|
+
type: "insert";
|
|
152
|
+
pageIndex: number;
|
|
153
|
+
markdown?: string | undefined;
|
|
154
|
+
sourcePdfPath?: string | undefined;
|
|
155
|
+
pdfOptions?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
156
|
+
}>, z.ZodObject<{
|
|
157
|
+
type: z.ZodLiteral<"delete">;
|
|
158
|
+
pageIndexes: z.ZodArray<z.ZodNumber, "many">;
|
|
159
|
+
}, "strip", z.ZodTypeAny, {
|
|
160
|
+
type: "delete";
|
|
161
|
+
pageIndexes: number[];
|
|
162
|
+
}, {
|
|
163
|
+
type: "delete";
|
|
164
|
+
pageIndexes: number[];
|
|
165
|
+
}>]>;
|
|
166
|
+
export declare const WritePdfArgsSchema: z.ZodObject<{
|
|
167
|
+
path: z.ZodString;
|
|
168
|
+
content: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodUnion<[z.ZodObject<{
|
|
169
|
+
type: z.ZodLiteral<"insert">;
|
|
170
|
+
pageIndex: z.ZodNumber;
|
|
171
|
+
markdown: z.ZodOptional<z.ZodString>;
|
|
172
|
+
sourcePdfPath: z.ZodOptional<z.ZodString>;
|
|
173
|
+
pdfOptions: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
|
|
174
|
+
}, "strip", z.ZodTypeAny, {
|
|
175
|
+
type: "insert";
|
|
176
|
+
pageIndex: number;
|
|
177
|
+
markdown?: string | undefined;
|
|
178
|
+
sourcePdfPath?: string | undefined;
|
|
179
|
+
pdfOptions?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
180
|
+
}, {
|
|
181
|
+
type: "insert";
|
|
182
|
+
pageIndex: number;
|
|
183
|
+
markdown?: string | undefined;
|
|
184
|
+
sourcePdfPath?: string | undefined;
|
|
185
|
+
pdfOptions?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
186
|
+
}>, z.ZodObject<{
|
|
187
|
+
type: z.ZodLiteral<"delete">;
|
|
188
|
+
pageIndexes: z.ZodArray<z.ZodNumber, "many">;
|
|
189
|
+
}, "strip", z.ZodTypeAny, {
|
|
190
|
+
type: "delete";
|
|
191
|
+
pageIndexes: number[];
|
|
192
|
+
}, {
|
|
193
|
+
type: "delete";
|
|
194
|
+
pageIndexes: number[];
|
|
195
|
+
}>]>, "many">]>, string | ({
|
|
196
|
+
type: "insert";
|
|
197
|
+
pageIndex: number;
|
|
198
|
+
markdown?: string | undefined;
|
|
199
|
+
sourcePdfPath?: string | undefined;
|
|
200
|
+
pdfOptions?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
201
|
+
} | {
|
|
202
|
+
type: "delete";
|
|
203
|
+
pageIndexes: number[];
|
|
204
|
+
})[], unknown>;
|
|
205
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
206
|
+
options: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
|
|
207
|
+
}, "strip", z.ZodTypeAny, {
|
|
208
|
+
path: string;
|
|
209
|
+
content: string | ({
|
|
210
|
+
type: "insert";
|
|
211
|
+
pageIndex: number;
|
|
212
|
+
markdown?: string | undefined;
|
|
213
|
+
sourcePdfPath?: string | undefined;
|
|
214
|
+
pdfOptions?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
215
|
+
} | {
|
|
216
|
+
type: "delete";
|
|
217
|
+
pageIndexes: number[];
|
|
218
|
+
})[];
|
|
219
|
+
options?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
220
|
+
outputPath?: string | undefined;
|
|
221
|
+
}, {
|
|
222
|
+
path: string;
|
|
223
|
+
options?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
224
|
+
content?: unknown;
|
|
225
|
+
outputPath?: string | undefined;
|
|
226
|
+
}>;
|
|
94
227
|
export declare const CreateDirectoryArgsSchema: z.ZodObject<{
|
|
95
228
|
path: z.ZodString;
|
|
96
229
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -125,20 +258,45 @@ export declare const GetFileInfoArgsSchema: z.ZodObject<{
|
|
|
125
258
|
}, {
|
|
126
259
|
path: string;
|
|
127
260
|
}>;
|
|
128
|
-
export declare const EditBlockArgsSchema: z.ZodObject<{
|
|
261
|
+
export declare const EditBlockArgsSchema: z.ZodEffects<z.ZodObject<{
|
|
129
262
|
file_path: z.ZodString;
|
|
130
|
-
old_string: z.ZodString
|
|
131
|
-
new_string: z.ZodString
|
|
263
|
+
old_string: z.ZodOptional<z.ZodString>;
|
|
264
|
+
new_string: z.ZodOptional<z.ZodString>;
|
|
132
265
|
expected_replacements: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
266
|
+
range: z.ZodOptional<z.ZodString>;
|
|
267
|
+
content: z.ZodOptional<z.ZodAny>;
|
|
268
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
133
269
|
}, "strip", z.ZodTypeAny, {
|
|
134
270
|
file_path: string;
|
|
135
|
-
old_string: string;
|
|
136
|
-
new_string: string;
|
|
137
271
|
expected_replacements: number;
|
|
272
|
+
options?: Record<string, any> | undefined;
|
|
273
|
+
range?: string | undefined;
|
|
274
|
+
content?: any;
|
|
275
|
+
old_string?: string | undefined;
|
|
276
|
+
new_string?: string | undefined;
|
|
277
|
+
}, {
|
|
278
|
+
file_path: string;
|
|
279
|
+
options?: Record<string, any> | undefined;
|
|
280
|
+
range?: string | undefined;
|
|
281
|
+
content?: any;
|
|
282
|
+
old_string?: string | undefined;
|
|
283
|
+
new_string?: string | undefined;
|
|
284
|
+
expected_replacements?: number | undefined;
|
|
285
|
+
}>, {
|
|
286
|
+
file_path: string;
|
|
287
|
+
expected_replacements: number;
|
|
288
|
+
options?: Record<string, any> | undefined;
|
|
289
|
+
range?: string | undefined;
|
|
290
|
+
content?: any;
|
|
291
|
+
old_string?: string | undefined;
|
|
292
|
+
new_string?: string | undefined;
|
|
138
293
|
}, {
|
|
139
294
|
file_path: string;
|
|
140
|
-
|
|
141
|
-
|
|
295
|
+
options?: Record<string, any> | undefined;
|
|
296
|
+
range?: string | undefined;
|
|
297
|
+
content?: any;
|
|
298
|
+
old_string?: string | undefined;
|
|
299
|
+
new_string?: string | undefined;
|
|
142
300
|
expected_replacements?: number | undefined;
|
|
143
301
|
}>;
|
|
144
302
|
export declare const InteractWithProcessArgsSchema: z.ZodObject<{
|
|
@@ -223,15 +381,12 @@ export declare const ListSearchesArgsSchema: z.ZodObject<{}, "strip", z.ZodTypeA
|
|
|
223
381
|
export declare const GetPromptsArgsSchema: z.ZodObject<{
|
|
224
382
|
action: z.ZodEnum<["get_prompt"]>;
|
|
225
383
|
promptId: z.ZodString;
|
|
226
|
-
anonymous_user_use_case: z.ZodOptional<z.ZodString>;
|
|
227
384
|
}, "strip", z.ZodTypeAny, {
|
|
228
385
|
action: "get_prompt";
|
|
229
386
|
promptId: string;
|
|
230
|
-
anonymous_user_use_case?: string | undefined;
|
|
231
387
|
}, {
|
|
232
388
|
action: "get_prompt";
|
|
233
389
|
promptId: string;
|
|
234
|
-
anonymous_user_use_case?: string | undefined;
|
|
235
390
|
}>;
|
|
236
391
|
export declare const GetRecentToolCallsArgsSchema: z.ZodObject<{
|
|
237
392
|
maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
package/dist/tools/schemas.js
CHANGED
|
@@ -23,6 +23,8 @@ export const StartProcessArgsSchema = z.object({
|
|
|
23
23
|
export const ReadProcessOutputArgsSchema = z.object({
|
|
24
24
|
pid: z.number(),
|
|
25
25
|
timeout_ms: z.number().optional(),
|
|
26
|
+
offset: z.number().optional(), // Line offset: 0=from last read, positive=absolute, negative=tail
|
|
27
|
+
length: z.number().optional(), // Max lines to return (default from config.fileReadLineLimit)
|
|
26
28
|
verbose_timing: z.boolean().optional(),
|
|
27
29
|
});
|
|
28
30
|
export const ForceTerminateArgsSchema = z.object({
|
|
@@ -38,6 +40,9 @@ export const ReadFileArgsSchema = z.object({
|
|
|
38
40
|
isUrl: z.boolean().optional().default(false),
|
|
39
41
|
offset: z.number().optional().default(0),
|
|
40
42
|
length: z.number().optional().default(1000),
|
|
43
|
+
sheet: z.string().optional(), // String only for MCP client compatibility (Cursor doesn't support union types in JSON Schema)
|
|
44
|
+
range: z.string().optional(),
|
|
45
|
+
options: z.record(z.any()).optional()
|
|
41
46
|
});
|
|
42
47
|
export const ReadMultipleFilesArgsSchema = z.object({
|
|
43
48
|
paths: z.array(z.string()),
|
|
@@ -47,6 +52,39 @@ export const WriteFileArgsSchema = z.object({
|
|
|
47
52
|
content: z.string(),
|
|
48
53
|
mode: z.enum(['rewrite', 'append']).default('rewrite'),
|
|
49
54
|
});
|
|
55
|
+
// PDF modification schemas - exported for reuse
|
|
56
|
+
export const PdfInsertOperationSchema = z.object({
|
|
57
|
+
type: z.literal('insert'),
|
|
58
|
+
pageIndex: z.number(),
|
|
59
|
+
markdown: z.string().optional(),
|
|
60
|
+
sourcePdfPath: z.string().optional(),
|
|
61
|
+
pdfOptions: z.object({}).passthrough().optional(),
|
|
62
|
+
});
|
|
63
|
+
export const PdfDeleteOperationSchema = z.object({
|
|
64
|
+
type: z.literal('delete'),
|
|
65
|
+
pageIndexes: z.array(z.number()),
|
|
66
|
+
});
|
|
67
|
+
export const PdfOperationSchema = z.union([PdfInsertOperationSchema, PdfDeleteOperationSchema]);
|
|
68
|
+
export const WritePdfArgsSchema = z.object({
|
|
69
|
+
path: z.string(),
|
|
70
|
+
// Preprocess content to handle JSON strings that should be parsed as arrays
|
|
71
|
+
content: z.preprocess((val) => {
|
|
72
|
+
// If it's a string that looks like JSON array, parse it
|
|
73
|
+
if (typeof val === 'string' && val.trim().startsWith('[')) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(val);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// If parsing fails, return as-is (might be markdown content)
|
|
79
|
+
return val;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Otherwise return as-is
|
|
83
|
+
return val;
|
|
84
|
+
}, z.union([z.string(), z.array(PdfOperationSchema)])),
|
|
85
|
+
outputPath: z.string().optional(),
|
|
86
|
+
options: z.object({}).passthrough().optional(), // Allow passing options to md-to-pdf
|
|
87
|
+
});
|
|
50
88
|
export const CreateDirectoryArgsSchema = z.object({
|
|
51
89
|
path: z.string(),
|
|
52
90
|
});
|
|
@@ -61,13 +99,23 @@ export const MoveFileArgsSchema = z.object({
|
|
|
61
99
|
export const GetFileInfoArgsSchema = z.object({
|
|
62
100
|
path: z.string(),
|
|
63
101
|
});
|
|
64
|
-
// Edit tools schema
|
|
102
|
+
// Edit tools schema - SIMPLIFIED from three modes to two
|
|
103
|
+
// Previously supported: text replacement, location-based edits (edits array), and range rewrites
|
|
104
|
+
// Now supports only: text replacement and range rewrites
|
|
105
|
+
// Removed 'edits' array parameter - location-based surgical edits were complex and unnecessary
|
|
106
|
+
// Range rewrites are more powerful and cover all structured file editing needs
|
|
65
107
|
export const EditBlockArgsSchema = z.object({
|
|
66
108
|
file_path: z.string(),
|
|
67
|
-
|
|
68
|
-
|
|
109
|
+
// Text file string replacement
|
|
110
|
+
old_string: z.string().optional(),
|
|
111
|
+
new_string: z.string().optional(),
|
|
69
112
|
expected_replacements: z.number().optional().default(1),
|
|
70
|
-
|
|
113
|
+
// Structured file range rewrite (Excel, etc.)
|
|
114
|
+
range: z.string().optional(),
|
|
115
|
+
content: z.any().optional(),
|
|
116
|
+
options: z.record(z.any()).optional()
|
|
117
|
+
}).refine(data => (data.old_string !== undefined && data.new_string !== undefined) ||
|
|
118
|
+
(data.range !== undefined && data.content !== undefined), { message: "Must provide either (old_string + new_string) or (range + content)" });
|
|
71
119
|
// Send input to process schema
|
|
72
120
|
export const InteractWithProcessArgsSchema = z.object({
|
|
73
121
|
pid: z.number(),
|
|
@@ -114,7 +162,8 @@ export const ListSearchesArgsSchema = z.object({});
|
|
|
114
162
|
export const GetPromptsArgsSchema = z.object({
|
|
115
163
|
action: z.enum(['get_prompt']),
|
|
116
164
|
promptId: z.string(),
|
|
117
|
-
|
|
165
|
+
// Disabled to check if it makes sense or should be removed or changed
|
|
166
|
+
// anonymous_user_use_case: z.string().optional(),
|
|
118
167
|
});
|
|
119
168
|
// Tool history schema
|
|
120
169
|
export const GetRecentToolCallsArgsSchema = z.object({
|
package/dist/types.d.ts
CHANGED
|
@@ -32,6 +32,9 @@ class FeatureFlagManager {
|
|
|
32
32
|
logger.debug('Periodic flag fetch failed:', err.message);
|
|
33
33
|
});
|
|
34
34
|
}, this.cacheMaxAge);
|
|
35
|
+
// Allow process to exit even if interval is pending
|
|
36
|
+
// This is critical for proper cleanup when MCP client disconnects
|
|
37
|
+
this.refreshInterval.unref();
|
|
35
38
|
logger.info(`Feature flags initialized (refresh every ${this.cacheMaxAge / 1000}s)`);
|
|
36
39
|
}
|
|
37
40
|
catch (error) {
|
|
@@ -89,7 +92,7 @@ class FeatureFlagManager {
|
|
|
89
92
|
*/
|
|
90
93
|
async fetchFlags() {
|
|
91
94
|
try {
|
|
92
|
-
|
|
95
|
+
// Don't log here - runs async and can interfere with MCP clients
|
|
93
96
|
const controller = new AbortController();
|
|
94
97
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
95
98
|
const response = await fetch(this.flagUrl, {
|
|
@@ -107,9 +110,9 @@ class FeatureFlagManager {
|
|
|
107
110
|
if (config.flags) {
|
|
108
111
|
this.flags = config.flags;
|
|
109
112
|
this.lastFetch = Date.now();
|
|
110
|
-
// Save to cache
|
|
113
|
+
// Save to cache (silently - don't log during async operations
|
|
114
|
+
// as it can interfere with MCP clients that close quickly)
|
|
111
115
|
await this.saveToCache(config);
|
|
112
|
-
logger.info(`Feature flags updated: ${Object.keys(this.flags).length} flags`);
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
catch (error) {
|
|
@@ -127,7 +130,7 @@ class FeatureFlagManager {
|
|
|
127
130
|
await fs.mkdir(configDir, { recursive: true });
|
|
128
131
|
}
|
|
129
132
|
await fs.writeFile(this.cachePath, JSON.stringify(config, null, 2), 'utf8');
|
|
130
|
-
|
|
133
|
+
// Don't log here - this runs async and can cause issues with MCP clients
|
|
131
134
|
}
|
|
132
135
|
catch (error) {
|
|
133
136
|
logger.warning('Failed to save feature flags to cache:', error);
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base interfaces and types for file handling system
|
|
3
|
+
* All file handlers implement the FileHandler interface
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base interface that all file handlers must implement
|
|
7
|
+
*/
|
|
8
|
+
export interface FileHandler {
|
|
9
|
+
/**
|
|
10
|
+
* Read file content
|
|
11
|
+
* @param path Validated file path
|
|
12
|
+
* @param options Read options (offset, length, sheet, etc.)
|
|
13
|
+
* @returns File result with content and metadata
|
|
14
|
+
*/
|
|
15
|
+
read(path: string, options?: ReadOptions): Promise<FileResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Write file (complete rewrite or append)
|
|
18
|
+
* @param path Validated file path
|
|
19
|
+
* @param content Content to write
|
|
20
|
+
* @param mode Write mode: 'rewrite' (default) or 'append'
|
|
21
|
+
*/
|
|
22
|
+
write(path: string, content: any, mode?: 'rewrite' | 'append'): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Edit a specific range (bulk rewrite)
|
|
25
|
+
* PRIMARY METHOD for structured file editing (Excel, etc.)
|
|
26
|
+
* Simpler and more powerful than location-based edits
|
|
27
|
+
* Supports:
|
|
28
|
+
* - Cell ranges: "Sheet1!A1:C10" with 2D array content
|
|
29
|
+
* - Whole sheets: "Sheet1" to replace entire sheet
|
|
30
|
+
* - Chunking: Update 1000 rows at a time for large files
|
|
31
|
+
*
|
|
32
|
+
* Currently implemented by: ExcelFileHandler
|
|
33
|
+
* TECHNICAL DEBT: TextFileHandler should also implement this for search/replace
|
|
34
|
+
* (logic currently in src/tools/edit.ts - see comments there)
|
|
35
|
+
*
|
|
36
|
+
* @param path Validated file path
|
|
37
|
+
* @param range Range identifier (e.g., "Sheet1!A1:C10" or "Sheet1")
|
|
38
|
+
* @param content New content for the range (2D array for Excel)
|
|
39
|
+
* @param options Additional format-specific options
|
|
40
|
+
* @returns Result with success status
|
|
41
|
+
*/
|
|
42
|
+
editRange?(path: string, range: string, content: any, options?: Record<string, any>): Promise<EditResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Get file metadata
|
|
45
|
+
* @param path Validated file path
|
|
46
|
+
* @returns File information including type-specific metadata
|
|
47
|
+
*/
|
|
48
|
+
getInfo(path: string): Promise<FileInfo>;
|
|
49
|
+
/**
|
|
50
|
+
* Check if this handler can handle the given file
|
|
51
|
+
* @param path File path
|
|
52
|
+
* @returns true if this handler supports this file type (can be async for content-based checks)
|
|
53
|
+
*/
|
|
54
|
+
canHandle(path: string): boolean | Promise<boolean>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Options for reading files
|
|
58
|
+
*/
|
|
59
|
+
export interface ReadOptions {
|
|
60
|
+
/** Whether the path is a URL */
|
|
61
|
+
isUrl?: boolean;
|
|
62
|
+
/** Starting line/row number (for text/excel) */
|
|
63
|
+
offset?: number;
|
|
64
|
+
/** Maximum number of lines/rows to read */
|
|
65
|
+
length?: number;
|
|
66
|
+
/** Excel-specific: Sheet name or index */
|
|
67
|
+
sheet?: string | number;
|
|
68
|
+
/** Excel-specific: Cell range (e.g., "A1:C10") */
|
|
69
|
+
range?: string;
|
|
70
|
+
/** Whether to include status messages (default: true) */
|
|
71
|
+
includeStatusMessage?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Result from reading a file
|
|
75
|
+
*/
|
|
76
|
+
export interface FileResult {
|
|
77
|
+
/** File content (string for text/csv, Buffer for binary, base64 string for images) */
|
|
78
|
+
content: string | Buffer;
|
|
79
|
+
/** MIME type of the content */
|
|
80
|
+
mimeType: string;
|
|
81
|
+
/** Type-specific metadata */
|
|
82
|
+
metadata?: FileMetadata;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* File-type specific metadata
|
|
86
|
+
*/
|
|
87
|
+
export interface FileMetadata {
|
|
88
|
+
/** For images */
|
|
89
|
+
isImage?: boolean;
|
|
90
|
+
/** For binary files */
|
|
91
|
+
isBinary?: boolean;
|
|
92
|
+
/** For Excel files */
|
|
93
|
+
isExcelFile?: boolean;
|
|
94
|
+
sheets?: ExcelSheet[];
|
|
95
|
+
fileSize?: number;
|
|
96
|
+
isLargeFile?: boolean;
|
|
97
|
+
/** For text files */
|
|
98
|
+
lineCount?: number;
|
|
99
|
+
/** For PDF files */
|
|
100
|
+
isPdf?: boolean;
|
|
101
|
+
author?: string;
|
|
102
|
+
title?: string;
|
|
103
|
+
totalPages?: number;
|
|
104
|
+
pages?: PdfPageItem[];
|
|
105
|
+
/** Error information if operation failed */
|
|
106
|
+
error?: boolean;
|
|
107
|
+
errorMessage?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* PDF page content item
|
|
111
|
+
*/
|
|
112
|
+
export interface PdfPageItem {
|
|
113
|
+
pageNumber: number;
|
|
114
|
+
text: string;
|
|
115
|
+
images: Array<{
|
|
116
|
+
data: string;
|
|
117
|
+
mimeType: string;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Excel sheet metadata
|
|
122
|
+
*/
|
|
123
|
+
export interface ExcelSheet {
|
|
124
|
+
/** Sheet name */
|
|
125
|
+
name: string;
|
|
126
|
+
/** Number of rows in sheet */
|
|
127
|
+
rowCount: number;
|
|
128
|
+
/** Number of columns in sheet */
|
|
129
|
+
colCount: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Result from edit operation (used by editRange)
|
|
133
|
+
*/
|
|
134
|
+
export interface EditResult {
|
|
135
|
+
/** Whether all edits succeeded */
|
|
136
|
+
success: boolean;
|
|
137
|
+
/** Number of edits successfully applied */
|
|
138
|
+
editsApplied: number;
|
|
139
|
+
/** Errors that occurred during editing */
|
|
140
|
+
errors?: Array<{
|
|
141
|
+
location: string;
|
|
142
|
+
error: string;
|
|
143
|
+
}>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* File information and metadata
|
|
147
|
+
*/
|
|
148
|
+
export interface FileInfo {
|
|
149
|
+
/** File size in bytes */
|
|
150
|
+
size: number;
|
|
151
|
+
/** Creation time */
|
|
152
|
+
created: Date;
|
|
153
|
+
/** Last modification time */
|
|
154
|
+
modified: Date;
|
|
155
|
+
/** Last access time */
|
|
156
|
+
accessed: Date;
|
|
157
|
+
/** Is this a directory */
|
|
158
|
+
isDirectory: boolean;
|
|
159
|
+
/** Is this a regular file */
|
|
160
|
+
isFile: boolean;
|
|
161
|
+
/** File permissions (octal string) */
|
|
162
|
+
permissions: string;
|
|
163
|
+
/** File type classification */
|
|
164
|
+
fileType: 'text' | 'excel' | 'image' | 'binary';
|
|
165
|
+
/** Type-specific metadata */
|
|
166
|
+
metadata?: FileMetadata;
|
|
167
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary file handler
|
|
3
|
+
* Handles binary files that aren't supported by other handlers (Excel, Image)
|
|
4
|
+
* Uses isBinaryFile for content-based detection
|
|
5
|
+
* Returns instructions to use start_process with appropriate tools
|
|
6
|
+
*/
|
|
7
|
+
import { FileHandler, ReadOptions, FileResult, FileInfo } from './base.js';
|
|
8
|
+
/**
|
|
9
|
+
* Binary file handler implementation
|
|
10
|
+
* Uses content-based detection via isBinaryFile
|
|
11
|
+
*/
|
|
12
|
+
export declare class BinaryFileHandler implements FileHandler {
|
|
13
|
+
canHandle(filePath: string): Promise<boolean>;
|
|
14
|
+
read(filePath: string, options?: ReadOptions): Promise<FileResult>;
|
|
15
|
+
write(path: string, content: any): Promise<void>;
|
|
16
|
+
getInfo(path: string): Promise<FileInfo>;
|
|
17
|
+
/**
|
|
18
|
+
* Generate instructions for handling binary files
|
|
19
|
+
*/
|
|
20
|
+
private getBinaryInstructions;
|
|
21
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary file handler
|
|
3
|
+
* Handles binary files that aren't supported by other handlers (Excel, Image)
|
|
4
|
+
* Uses isBinaryFile for content-based detection
|
|
5
|
+
* Returns instructions to use start_process with appropriate tools
|
|
6
|
+
*/
|
|
7
|
+
import fs from "fs/promises";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import { isBinaryFile } from 'isbinaryfile';
|
|
10
|
+
/**
|
|
11
|
+
* Binary file handler implementation
|
|
12
|
+
* Uses content-based detection via isBinaryFile
|
|
13
|
+
*/
|
|
14
|
+
export class BinaryFileHandler {
|
|
15
|
+
async canHandle(filePath) {
|
|
16
|
+
// Content-based binary detection using isBinaryFile
|
|
17
|
+
try {
|
|
18
|
+
return await isBinaryFile(filePath);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
// If we can't check (file doesn't exist, etc.), don't handle it
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async read(filePath, options) {
|
|
26
|
+
const instructions = this.getBinaryInstructions(filePath);
|
|
27
|
+
return {
|
|
28
|
+
content: instructions,
|
|
29
|
+
mimeType: 'text/plain',
|
|
30
|
+
metadata: {
|
|
31
|
+
isBinary: true
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async write(path, content) {
|
|
36
|
+
throw new Error('Cannot write binary files directly. Use start_process with appropriate tools (Python, Node.js libraries, command-line utilities).');
|
|
37
|
+
}
|
|
38
|
+
async getInfo(path) {
|
|
39
|
+
const stats = await fs.stat(path);
|
|
40
|
+
return {
|
|
41
|
+
size: stats.size,
|
|
42
|
+
created: stats.birthtime,
|
|
43
|
+
modified: stats.mtime,
|
|
44
|
+
accessed: stats.atime,
|
|
45
|
+
isDirectory: stats.isDirectory(),
|
|
46
|
+
isFile: stats.isFile(),
|
|
47
|
+
permissions: stats.mode.toString(8).slice(-3),
|
|
48
|
+
fileType: 'binary',
|
|
49
|
+
metadata: {
|
|
50
|
+
isBinary: true
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate instructions for handling binary files
|
|
56
|
+
*/
|
|
57
|
+
getBinaryInstructions(filePath) {
|
|
58
|
+
const fileName = path.basename(filePath);
|
|
59
|
+
return `Cannot read binary file as text: ${fileName}
|
|
60
|
+
|
|
61
|
+
Use start_process + interact_with_process to analyze binary files with appropriate tools (Node.js or Python libraries, command-line utilities, etc.).
|
|
62
|
+
|
|
63
|
+
The read_file tool only handles text files, images, and Excel files.`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Excel file handler using ExcelJS
|
|
3
|
+
* Handles reading, writing, and editing Excel files (.xlsx, .xls, .xlsm)
|
|
4
|
+
*/
|
|
5
|
+
import { FileHandler, ReadOptions, FileResult, EditResult, FileInfo } from './base.js';
|
|
6
|
+
/**
|
|
7
|
+
* Excel file handler implementation using ExcelJS
|
|
8
|
+
* Supports: .xlsx, .xls, .xlsm files
|
|
9
|
+
*/
|
|
10
|
+
export declare class ExcelFileHandler implements FileHandler {
|
|
11
|
+
canHandle(path: string): boolean;
|
|
12
|
+
read(path: string, options?: ReadOptions): Promise<FileResult>;
|
|
13
|
+
write(path: string, content: any, mode?: 'rewrite' | 'append'): Promise<void>;
|
|
14
|
+
editRange(path: string, range: string, content: any, options?: Record<string, any>): Promise<EditResult>;
|
|
15
|
+
getInfo(path: string): Promise<FileInfo>;
|
|
16
|
+
private checkFileSize;
|
|
17
|
+
private extractMetadata;
|
|
18
|
+
private worksheetToArray;
|
|
19
|
+
private writeDataToSheet;
|
|
20
|
+
private writeRowsStartingAt;
|
|
21
|
+
private parseRange;
|
|
22
|
+
private parseCellRange;
|
|
23
|
+
private columnToNumber;
|
|
24
|
+
}
|