@mcpc-tech/core 0.3.8 → 0.3.10

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.
@@ -0,0 +1,382 @@
1
+ #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/large-result.ts
31
+ var large_result_exports = {};
32
+ __export(large_result_exports, {
33
+ createLargeResultPlugin: () => createLargeResultPlugin,
34
+ createPlugin: () => createPlugin,
35
+ default: () => large_result_default
36
+ });
37
+ module.exports = __toCommonJS(large_result_exports);
38
+ var import_promises = require("node:fs/promises");
39
+ var import_node_path3 = require("node:path");
40
+ var import_node_os2 = require("node:os");
41
+
42
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/search-tool.js
43
+ var import_ripgrep_napi = __toESM(require("@mcpc-tech/ripgrep-napi"), 1);
44
+ var import_node_os = require("node:os");
45
+
46
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/utils/schema.js
47
+ var schemaSymbol = Symbol.for("mcpc.schema");
48
+ var vercelSchemaSymbol = Symbol.for("vercel.ai.schema");
49
+ var validatorSymbol = Symbol.for("mcpc.validator");
50
+ function jsonSchema(schema, options = {}) {
51
+ if (isWrappedSchema(schema)) {
52
+ return schema;
53
+ }
54
+ return {
55
+ [schemaSymbol]: true,
56
+ [validatorSymbol]: true,
57
+ _type: void 0,
58
+ jsonSchema: schema,
59
+ validate: options.validate
60
+ };
61
+ }
62
+ function isWrappedSchema(value) {
63
+ return typeof value === "object" && value !== null && (schemaSymbol in value && value[schemaSymbol] === true || vercelSchemaSymbol in value && value[vercelSchemaSymbol] === true);
64
+ }
65
+
66
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/search-tool.js
67
+ var import_node_path = require("node:path");
68
+ var import_node_path2 = require("node:path");
69
+ function createSearchPlugin(options = {}) {
70
+ const maxResults = options.maxResults || 20;
71
+ const maxOutputSize = options.maxOutputSize || 5e3;
72
+ const allowedSearchDir = options.allowedDir || (0, import_node_os.tmpdir)();
73
+ const timeoutMs = options.timeoutMs || 3e4;
74
+ const global = options.global ?? true;
75
+ const activeTimeouts = /* @__PURE__ */ new Set();
76
+ return {
77
+ name: "plugin-search",
78
+ version: "1.0.0",
79
+ configureServer: (server) => {
80
+ const defaultDescription = `Search for text patterns in files and directories. Use this to find specific content, code, or information within files. Provide a simple literal string or a regular expression. If your pattern is a regex, ensure it's valid; otherwise use quotes or escape special characters to treat it as a literal string.
81
+ Only search within the allowed directory: ${allowedSearchDir}`;
82
+ const toolDescription = options.toolDescription || defaultDescription;
83
+ server.tool("search-tool-result", toolDescription, jsonSchema({
84
+ type: "object",
85
+ properties: {
86
+ pattern: {
87
+ type: "string",
88
+ description: "Text to search for. Can be a plain string or a regular expression. For regexes, don't include delimiters (e.g. use `^foo` not `/^foo/`). If you get a regex parse error, try escaping special chars or using a simpler literal search."
89
+ },
90
+ path: {
91
+ type: "string",
92
+ description: "File or folder path to limit the search (optional). Must be within the allowed directory."
93
+ },
94
+ maxResults: {
95
+ type: "number",
96
+ description: "Maximum number of matches to return (optional). Lower this to reduce output size and runtime."
97
+ }
98
+ },
99
+ required: [
100
+ "pattern"
101
+ ]
102
+ }), async (args) => {
103
+ const isBroad = (raw) => {
104
+ const t = (raw ?? "").trim();
105
+ if (!t) return true;
106
+ if (/^[*.\s]{2,}$/.test(t)) return true;
107
+ if (t === ".*" || t === "." || t === "^.*$") return true;
108
+ if (/^\^?\.\*\$?$/.test(t)) return true;
109
+ if (/^\\s?\*+$/.test(t)) return true;
110
+ return false;
111
+ };
112
+ const appendMatchSafely = (current, addition, limit) => {
113
+ if ((current + addition).length > limit) {
114
+ return {
115
+ current,
116
+ added: false
117
+ };
118
+ }
119
+ return {
120
+ current: current + addition,
121
+ added: true
122
+ };
123
+ };
124
+ let timeoutId;
125
+ try {
126
+ const requestedPath = args.path || allowedSearchDir;
127
+ const limit = args.maxResults || maxResults;
128
+ if (args.path) {
129
+ const resolvedRequested = (0, import_node_path.resolve)(args.path);
130
+ const resolvedAllowed = (0, import_node_path.resolve)(allowedSearchDir);
131
+ const relativePath = (0, import_node_path2.relative)(resolvedAllowed, resolvedRequested);
132
+ if (relativePath && relativePath.startsWith("..")) {
133
+ return {
134
+ content: [
135
+ {
136
+ type: "text",
137
+ text: `\u274C Path "${args.path}" not allowed. Must be within: ${allowedSearchDir}`
138
+ }
139
+ ],
140
+ isError: true
141
+ };
142
+ }
143
+ }
144
+ const searchPath = requestedPath;
145
+ const rawPattern = args.pattern ?? "";
146
+ if (isBroad(rawPattern)) {
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: `\u274C Search pattern too broad: "${rawPattern}"
152
+ Provide a more specific pattern (e.g. include a filename fragment, a keyword, or limit with the "path" parameter). Avoid patterns that only contain wildcards like "*" or ".*".`
153
+ }
154
+ ],
155
+ isError: true
156
+ };
157
+ }
158
+ const timeoutPromise = new Promise((_, reject) => {
159
+ timeoutId = setTimeout(() => {
160
+ reject(new Error(`Search timeout after ${timeoutMs}ms`));
161
+ }, timeoutMs);
162
+ activeTimeouts.add(timeoutId);
163
+ });
164
+ const searchPromise = new Promise((resolve2, reject) => {
165
+ try {
166
+ const result2 = import_ripgrep_napi.default.search(args.pattern, [
167
+ searchPath
168
+ ]);
169
+ resolve2(result2);
170
+ } catch (error) {
171
+ reject(error);
172
+ }
173
+ });
174
+ const result = await Promise.race([
175
+ searchPromise,
176
+ timeoutPromise
177
+ ]);
178
+ if (timeoutId) {
179
+ clearTimeout(timeoutId);
180
+ activeTimeouts.delete(timeoutId);
181
+ }
182
+ if (!result.success || !result.matches?.length) {
183
+ return {
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: `No matches found for: "${args.pattern}"
188
+
189
+ Try:
190
+ - **Simpler pattern** or \`*\`
191
+ - Check if files exist in: ${searchPath}
192
+ - Use specific file path`
193
+ }
194
+ ]
195
+ };
196
+ }
197
+ const matches = result.matches.slice(0, limit);
198
+ let output = `Found ${result.matches.length} matches (showing up to ${matches.length}):
199
+
200
+ `;
201
+ let matchesIncluded = 0;
202
+ for (const match of matches) {
203
+ const baseMatchText = `**${match.path}:${match.lineNumber}**
204
+ `;
205
+ const fullMatchText = `${baseMatchText}\`\`\`
206
+ ${match.line}
207
+ \`\`\`
208
+
209
+ `;
210
+ const res = appendMatchSafely(output, fullMatchText, maxOutputSize);
211
+ if (!res.added) {
212
+ if (matchesIncluded === 0) {
213
+ const remainingSpace = maxOutputSize - output.length - 100;
214
+ if (remainingSpace > 50) {
215
+ const truncatedLine = match.line.slice(0, remainingSpace);
216
+ output += `${baseMatchText}\`\`\`
217
+ ${truncatedLine}...
218
+ \`\`\`
219
+
220
+ `;
221
+ output += `\u26A0\uFE0F Content truncated
222
+ `;
223
+ matchesIncluded++;
224
+ } else {
225
+ output += `\u26A0\uFE0F Content too large, use specific file path
226
+ `;
227
+ }
228
+ }
229
+ break;
230
+ }
231
+ output = res.current;
232
+ matchesIncluded++;
233
+ }
234
+ if (matchesIncluded < matches.length) {
235
+ output += `
236
+ \u26A0\uFE0F Showing ${matchesIncluded}/${matches.length} matches (size limit)
237
+ `;
238
+ output += `
239
+ For more results:
240
+ `;
241
+ output += `- Use specific pattern: "${args.pattern} keyword"
242
+ `;
243
+ output += `- Search specific file: {"pattern": "${args.pattern}", "path": "/file.txt"}
244
+ `;
245
+ output += `- Use fewer results: {"maxResults": 5}`;
246
+ }
247
+ return {
248
+ content: [
249
+ {
250
+ type: "text",
251
+ text: output
252
+ }
253
+ ]
254
+ };
255
+ } catch (error) {
256
+ if (timeoutId) {
257
+ clearTimeout(timeoutId);
258
+ activeTimeouts.delete(timeoutId);
259
+ }
260
+ const errorMsg = error instanceof Error ? error.message : String(error);
261
+ const isTimeout = errorMsg.includes("timeout");
262
+ return {
263
+ content: [
264
+ {
265
+ type: "text",
266
+ text: `Search error: ${errorMsg}
267
+
268
+ ${isTimeout ? `Timeout after ${timeoutMs}ms. Try simpler pattern or smaller directory.` : `Check pattern syntax or directory exists.`}`
269
+ }
270
+ ]
271
+ };
272
+ }
273
+ }, {
274
+ internal: !global
275
+ });
276
+ },
277
+ dispose: () => {
278
+ for (const timeoutId of activeTimeouts) {
279
+ clearTimeout(timeoutId);
280
+ }
281
+ activeTimeouts.clear();
282
+ }
283
+ };
284
+ }
285
+ var defaultSearchPlugin = createSearchPlugin({
286
+ global: true,
287
+ maxResults: 20,
288
+ maxOutputSize: 5e3,
289
+ caseSensitive: false,
290
+ timeoutMs: 3e4
291
+ });
292
+
293
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/large-result.ts
294
+ function createLargeResultPlugin(options = {}) {
295
+ const maxSize = options.maxSize || 8e3;
296
+ const previewSize = options.previewSize || 4e3;
297
+ let tempDir = options.tempDir || null;
298
+ const configuredServers = /* @__PURE__ */ new Map();
299
+ const defaultSearchDescription = `Search within large tool result files that were saved due to size limits. Use when: a tool result was saved to file because it exceeded the context limit. Do NOT use this tool before calling the actual tool first. Provide specific keywords or patterns related to the content you're looking for.`;
300
+ const searchConfig = {
301
+ maxResults: options.search?.maxResults || 15,
302
+ maxOutputSize: options.search?.maxOutputSize || 4e3,
303
+ toolDescription: options.search?.toolDescription || defaultSearchDescription,
304
+ global: true
305
+ };
306
+ return {
307
+ name: "plugin-large-result-handler",
308
+ version: "1.0.0",
309
+ dependencies: [],
310
+ // Search plugin will be added dynamically
311
+ configureServer: async (server) => {
312
+ if (!configuredServers.has(server)) {
313
+ const searchPlugin = createSearchPlugin(searchConfig);
314
+ await server.addPlugin(searchPlugin);
315
+ configuredServers.set(server, true);
316
+ }
317
+ },
318
+ transformTool: (tool, context) => {
319
+ const originalExecute = tool.execute;
320
+ tool.execute = async (args) => {
321
+ try {
322
+ const result = await originalExecute(args);
323
+ const resultText = JSON.stringify(result);
324
+ if (resultText.length <= maxSize) {
325
+ return result;
326
+ }
327
+ if (!tempDir) {
328
+ tempDir = await (0, import_promises.mkdtemp)((0, import_node_path3.join)((0, import_node_os2.tmpdir)(), "mcpc-results-"));
329
+ }
330
+ const safeToolName = encodeURIComponent(context.toolName ?? "tool");
331
+ const fileName = `${safeToolName}-${Date.now()}.txt`;
332
+ const filePath = (0, import_node_path3.join)(tempDir, fileName);
333
+ await (0, import_promises.writeFile)(filePath, resultText);
334
+ const preview = resultText.slice(0, previewSize);
335
+ const sizeKB = (resultText.length / 1024).toFixed(1);
336
+ return {
337
+ content: [
338
+ {
339
+ type: "text",
340
+ text: `**Result too large (${resultText.length} chars), saved to file**
341
+
342
+ \u{1F4C1} **File:** ${filePath}
343
+ \u{1F4CA} **Size:** ${sizeKB} KB
344
+
345
+ **Preview (${previewSize} chars):**
346
+ \`\`\`
347
+ ${preview}
348
+ \`\`\`
349
+
350
+ **To read/understand the full content:**
351
+ - Use the \`search-tool-result\` tool with pattern: \`search-tool-result {"pattern": "your-search-term"}\`
352
+ - Search supports regex patterns for advanced queries`
353
+ }
354
+ ]
355
+ };
356
+ } catch (error) {
357
+ const errorMsg = error instanceof Error ? error.message : String(error);
358
+ console.error(
359
+ `Large result plugin error for ${context.toolName}: ${errorMsg}`
360
+ );
361
+ throw error;
362
+ }
363
+ };
364
+ return tool;
365
+ },
366
+ dispose: () => {
367
+ configuredServers.clear();
368
+ tempDir = null;
369
+ }
370
+ };
371
+ }
372
+ var defaultLargeResultPlugin = createLargeResultPlugin({
373
+ maxSize: 8e3,
374
+ previewSize: 4e3
375
+ });
376
+ var createPlugin = createLargeResultPlugin;
377
+ var large_result_default = defaultLargeResultPlugin;
378
+ // Annotate the CommonJS export names for ESM import in node:
379
+ 0 && (module.exports = {
380
+ createLargeResultPlugin,
381
+ createPlugin
382
+ });
@@ -45,8 +45,10 @@ function createSearchPlugin(options = {}) {
45
45
  name: "plugin-search",
46
46
  version: "1.0.0",
47
47
  configureServer: (server) => {
48
- server.tool("search-tool-result", `Search for text patterns in files and directories. Use this to find specific content, code, or information within files. Provide a simple literal string or a regular expression. If your pattern is a regex, ensure it's valid; otherwise use quotes or escape special characters to treat it as a literal string.
49
- Only search within the allowed directory: ${allowedSearchDir}`, jsonSchema({
48
+ const defaultDescription = `Search for text patterns in files and directories. Use this to find specific content, code, or information within files. Provide a simple literal string or a regular expression. If your pattern is a regex, ensure it's valid; otherwise use quotes or escape special characters to treat it as a literal string.
49
+ Only search within the allowed directory: ${allowedSearchDir}`;
50
+ const toolDescription = options.toolDescription || defaultDescription;
51
+ server.tool("search-tool-result", toolDescription, jsonSchema({
50
52
  type: "object",
51
53
  properties: {
52
54
  pattern: {
@@ -262,9 +264,11 @@ function createLargeResultPlugin(options = {}) {
262
264
  const previewSize = options.previewSize || 4e3;
263
265
  let tempDir = options.tempDir || null;
264
266
  const configuredServers = /* @__PURE__ */ new Map();
267
+ const defaultSearchDescription = `Search within large tool result files that were saved due to size limits. Use when: a tool result was saved to file because it exceeded the context limit. Do NOT use this tool before calling the actual tool first. Provide specific keywords or patterns related to the content you're looking for.`;
265
268
  const searchConfig = {
266
269
  maxResults: options.search?.maxResults || 15,
267
270
  maxOutputSize: options.search?.maxOutputSize || 4e3,
271
+ toolDescription: options.search?.toolDescription || defaultSearchDescription,
268
272
  global: true
269
273
  };
270
274
  return {
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/search-tool.ts
31
+ var search_tool_exports = {};
32
+ __export(search_tool_exports, {
33
+ createPlugin: () => createPlugin,
34
+ createSearchPlugin: () => createSearchPlugin,
35
+ default: () => search_tool_default
36
+ });
37
+ module.exports = __toCommonJS(search_tool_exports);
38
+ var import_ripgrep_napi = __toESM(require("@mcpc-tech/ripgrep-napi"), 1);
39
+ var import_node_os = require("node:os");
40
+
41
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/utils/schema.js
42
+ var schemaSymbol = Symbol.for("mcpc.schema");
43
+ var vercelSchemaSymbol = Symbol.for("vercel.ai.schema");
44
+ var validatorSymbol = Symbol.for("mcpc.validator");
45
+ function jsonSchema(schema, options = {}) {
46
+ if (isWrappedSchema(schema)) {
47
+ return schema;
48
+ }
49
+ return {
50
+ [schemaSymbol]: true,
51
+ [validatorSymbol]: true,
52
+ _type: void 0,
53
+ jsonSchema: schema,
54
+ validate: options.validate
55
+ };
56
+ }
57
+ function isWrappedSchema(value) {
58
+ return typeof value === "object" && value !== null && (schemaSymbol in value && value[schemaSymbol] === true || vercelSchemaSymbol in value && value[vercelSchemaSymbol] === true);
59
+ }
60
+
61
+ // __mcpc__core_latest/node_modules/@mcpc/core/src/plugins/search-tool.ts
62
+ var import_node_path = require("node:path");
63
+ var import_node_path2 = require("node:path");
64
+ function createSearchPlugin(options = {}) {
65
+ const maxResults = options.maxResults || 20;
66
+ const maxOutputSize = options.maxOutputSize || 5e3;
67
+ const allowedSearchDir = options.allowedDir || (0, import_node_os.tmpdir)();
68
+ const timeoutMs = options.timeoutMs || 3e4;
69
+ const global = options.global ?? true;
70
+ const activeTimeouts = /* @__PURE__ */ new Set();
71
+ return {
72
+ name: "plugin-search",
73
+ version: "1.0.0",
74
+ configureServer: (server) => {
75
+ const defaultDescription = `Search for text patterns in files and directories. Use this to find specific content, code, or information within files. Provide a simple literal string or a regular expression. If your pattern is a regex, ensure it's valid; otherwise use quotes or escape special characters to treat it as a literal string.
76
+ Only search within the allowed directory: ${allowedSearchDir}`;
77
+ const toolDescription = options.toolDescription || defaultDescription;
78
+ server.tool(
79
+ "search-tool-result",
80
+ toolDescription,
81
+ jsonSchema({
82
+ type: "object",
83
+ properties: {
84
+ pattern: {
85
+ type: "string",
86
+ description: "Text to search for. Can be a plain string or a regular expression. For regexes, don't include delimiters (e.g. use `^foo` not `/^foo/`). If you get a regex parse error, try escaping special chars or using a simpler literal search."
87
+ },
88
+ path: {
89
+ type: "string",
90
+ description: "File or folder path to limit the search (optional). Must be within the allowed directory."
91
+ },
92
+ maxResults: {
93
+ type: "number",
94
+ description: "Maximum number of matches to return (optional). Lower this to reduce output size and runtime."
95
+ }
96
+ },
97
+ required: ["pattern"]
98
+ }),
99
+ async (args) => {
100
+ const isBroad = (raw) => {
101
+ const t = (raw ?? "").trim();
102
+ if (!t) return true;
103
+ if (/^[*.\s]{2,}$/.test(t)) return true;
104
+ if (t === ".*" || t === "." || t === "^.*$") return true;
105
+ if (/^\^?\.\*\$?$/.test(t)) return true;
106
+ if (/^\\s?\*+$/.test(t)) return true;
107
+ return false;
108
+ };
109
+ const appendMatchSafely = (current, addition, limit) => {
110
+ if ((current + addition).length > limit) {
111
+ return { current, added: false };
112
+ }
113
+ return { current: current + addition, added: true };
114
+ };
115
+ let timeoutId;
116
+ try {
117
+ const requestedPath = args.path || allowedSearchDir;
118
+ const limit = args.maxResults || maxResults;
119
+ if (args.path) {
120
+ const resolvedRequested = (0, import_node_path.resolve)(args.path);
121
+ const resolvedAllowed = (0, import_node_path.resolve)(allowedSearchDir);
122
+ const relativePath = (0, import_node_path2.relative)(resolvedAllowed, resolvedRequested);
123
+ if (relativePath && relativePath.startsWith("..")) {
124
+ return {
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: `\u274C Path "${args.path}" not allowed. Must be within: ${allowedSearchDir}`
129
+ }
130
+ ],
131
+ isError: true
132
+ };
133
+ }
134
+ }
135
+ const searchPath = requestedPath;
136
+ const rawPattern = args.pattern ?? "";
137
+ if (isBroad(rawPattern)) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `\u274C Search pattern too broad: "${rawPattern}"
143
+ Provide a more specific pattern (e.g. include a filename fragment, a keyword, or limit with the "path" parameter). Avoid patterns that only contain wildcards like "*" or ".*".`
144
+ }
145
+ ],
146
+ isError: true
147
+ };
148
+ }
149
+ const timeoutPromise = new Promise((_, reject) => {
150
+ timeoutId = setTimeout(() => {
151
+ reject(new Error(`Search timeout after ${timeoutMs}ms`));
152
+ }, timeoutMs);
153
+ activeTimeouts.add(timeoutId);
154
+ });
155
+ const searchPromise = new Promise((resolve2, reject) => {
156
+ try {
157
+ const result2 = import_ripgrep_napi.default.search(args.pattern, [searchPath]);
158
+ resolve2(result2);
159
+ } catch (error) {
160
+ reject(error);
161
+ }
162
+ });
163
+ const result = await Promise.race([
164
+ searchPromise,
165
+ timeoutPromise
166
+ ]);
167
+ if (timeoutId) {
168
+ clearTimeout(timeoutId);
169
+ activeTimeouts.delete(timeoutId);
170
+ }
171
+ if (!result.success || !result.matches?.length) {
172
+ return {
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: `No matches found for: "${args.pattern}"
177
+
178
+ Try:
179
+ - **Simpler pattern** or \`*\`
180
+ - Check if files exist in: ${searchPath}
181
+ - Use specific file path`
182
+ }
183
+ ]
184
+ };
185
+ }
186
+ const matches = result.matches.slice(0, limit);
187
+ let output = `Found ${result.matches.length} matches (showing up to ${matches.length}):
188
+
189
+ `;
190
+ let matchesIncluded = 0;
191
+ for (const match of matches) {
192
+ const baseMatchText = `**${match.path}:${match.lineNumber}**
193
+ `;
194
+ const fullMatchText = `${baseMatchText}\`\`\`
195
+ ${match.line}
196
+ \`\`\`
197
+
198
+ `;
199
+ const res = appendMatchSafely(
200
+ output,
201
+ fullMatchText,
202
+ maxOutputSize
203
+ );
204
+ if (!res.added) {
205
+ if (matchesIncluded === 0) {
206
+ const remainingSpace = maxOutputSize - output.length - 100;
207
+ if (remainingSpace > 50) {
208
+ const truncatedLine = match.line.slice(0, remainingSpace);
209
+ output += `${baseMatchText}\`\`\`
210
+ ${truncatedLine}...
211
+ \`\`\`
212
+
213
+ `;
214
+ output += `\u26A0\uFE0F Content truncated
215
+ `;
216
+ matchesIncluded++;
217
+ } else {
218
+ output += `\u26A0\uFE0F Content too large, use specific file path
219
+ `;
220
+ }
221
+ }
222
+ break;
223
+ }
224
+ output = res.current;
225
+ matchesIncluded++;
226
+ }
227
+ if (matchesIncluded < matches.length) {
228
+ output += `
229
+ \u26A0\uFE0F Showing ${matchesIncluded}/${matches.length} matches (size limit)
230
+ `;
231
+ output += `
232
+ For more results:
233
+ `;
234
+ output += `- Use specific pattern: "${args.pattern} keyword"
235
+ `;
236
+ output += `- Search specific file: {"pattern": "${args.pattern}", "path": "/file.txt"}
237
+ `;
238
+ output += `- Use fewer results: {"maxResults": 5}`;
239
+ }
240
+ return {
241
+ content: [
242
+ {
243
+ type: "text",
244
+ text: output
245
+ }
246
+ ]
247
+ };
248
+ } catch (error) {
249
+ if (timeoutId) {
250
+ clearTimeout(timeoutId);
251
+ activeTimeouts.delete(timeoutId);
252
+ }
253
+ const errorMsg = error instanceof Error ? error.message : String(error);
254
+ const isTimeout = errorMsg.includes("timeout");
255
+ return {
256
+ content: [
257
+ {
258
+ type: "text",
259
+ text: `Search error: ${errorMsg}
260
+
261
+ ${isTimeout ? `Timeout after ${timeoutMs}ms. Try simpler pattern or smaller directory.` : `Check pattern syntax or directory exists.`}`
262
+ }
263
+ ]
264
+ };
265
+ }
266
+ },
267
+ { internal: !global }
268
+ );
269
+ },
270
+ dispose: () => {
271
+ for (const timeoutId of activeTimeouts) {
272
+ clearTimeout(timeoutId);
273
+ }
274
+ activeTimeouts.clear();
275
+ }
276
+ };
277
+ }
278
+ var defaultSearchPlugin = createSearchPlugin({
279
+ global: true,
280
+ maxResults: 20,
281
+ maxOutputSize: 5e3,
282
+ caseSensitive: false,
283
+ timeoutMs: 3e4
284
+ });
285
+ var createPlugin = createSearchPlugin;
286
+ var search_tool_default = defaultSearchPlugin;
287
+ // Annotate the CommonJS export names for ESM import in node:
288
+ 0 && (module.exports = {
289
+ createPlugin,
290
+ createSearchPlugin
291
+ });