@probelabs/probe 0.6.0-rc148 → 0.6.0-rc149

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.
@@ -920,9 +920,7 @@ Examples:
920
920
  </search>
921
921
 
922
922
  <extract>
923
- <path>src/config.js</path>
924
- <start_line>15</start_line>
925
- <end_line>25</end_line>
923
+ <targets>src/config.js:15-25</targets>
926
924
  </extract>
927
925
 
928
926
  <attempt_completion>
@@ -2888,7 +2888,7 @@ async function extract(options) {
2888
2888
  const hasInputFile = !!options.inputFile;
2889
2889
  const hasContent = options.content !== void 0 && options.content !== null;
2890
2890
  if (!hasFiles && !hasInputFile && !hasContent) {
2891
- throw new Error("Either files array, inputFile, or content must be provided");
2891
+ throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
2892
2892
  }
2893
2893
  const binaryPath = await getBinaryPath(options.binaryOptions || {});
2894
2894
  const filteredOptions = { ...options };
@@ -7153,6 +7153,27 @@ var init_zod = __esm({
7153
7153
  });
7154
7154
 
7155
7155
  // src/tools/common.js
7156
+ function getValidParamsForTool(toolName) {
7157
+ const schemaMap = {
7158
+ search: searchSchema,
7159
+ query: querySchema,
7160
+ extract: extractSchema,
7161
+ delegate: delegateSchema,
7162
+ bash: bashSchema,
7163
+ attempt_completion: attemptCompletionSchema
7164
+ };
7165
+ const schema = schemaMap[toolName];
7166
+ if (!schema) {
7167
+ return ["path", "directory", "pattern", "recursive", "includeHidden", "task", "files", "autoCommits", "result"];
7168
+ }
7169
+ if (toolName === "attempt_completion") {
7170
+ return ["result"];
7171
+ }
7172
+ if (schema && schema._def && schema._def.shape) {
7173
+ return Object.keys(schema._def.shape());
7174
+ }
7175
+ return [];
7176
+ }
7156
7177
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
7157
7178
  for (const toolName of validTools) {
7158
7179
  const openTag = `<${toolName}>`;
@@ -7171,35 +7192,8 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
7171
7192
  closeIndex
7172
7193
  );
7173
7194
  const params = {};
7174
- const commonParams = [
7175
- "query",
7176
- "file_path",
7177
- "line",
7178
- "end_line",
7179
- "path",
7180
- "recursive",
7181
- "includeHidden",
7182
- "max_results",
7183
- "maxResults",
7184
- "result",
7185
- "command",
7186
- "description",
7187
- "task",
7188
- "param",
7189
- "pattern",
7190
- "allow_tests",
7191
- "exact",
7192
- "maxTokens",
7193
- "language",
7194
- "input_content",
7195
- "context_lines",
7196
- "format",
7197
- "directory",
7198
- "autoCommits",
7199
- "files",
7200
- "targets"
7201
- ];
7202
- for (const paramName of commonParams) {
7195
+ const validParams = getValidParamsForTool(toolName);
7196
+ for (const paramName of validParams) {
7203
7197
  const paramOpenTag = `<${paramName}>`;
7204
7198
  const paramCloseTag = `</${paramName}>`;
7205
7199
  const paramOpenIndex = innerContent.indexOf(paramOpenTag);
@@ -7209,7 +7203,7 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
7209
7203
  let paramCloseIndex = innerContent.indexOf(paramCloseTag, paramOpenIndex + paramOpenTag.length);
7210
7204
  if (paramCloseIndex === -1) {
7211
7205
  let nextTagIndex = innerContent.length;
7212
- for (const nextParam of commonParams) {
7206
+ for (const nextParam of validParams) {
7213
7207
  const nextOpenTag = `<${nextParam}>`;
7214
7208
  const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
7215
7209
  if (nextIndex !== -1 && nextIndex < nextTagIndex) {
@@ -7271,13 +7265,8 @@ var init_common = __esm({
7271
7265
  "use strict";
7272
7266
  init_zod();
7273
7267
  searchSchema = external_exports.object({
7274
- query: external_exports.string().describe("Search query with Elasticsearch syntax. Use + for important terms."),
7275
- path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
7276
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results"),
7277
- exact: external_exports.boolean().optional().default(false).describe("Perform exact search without tokenization (case-insensitive)"),
7278
- maxResults: external_exports.number().optional().describe("Maximum number of results to return"),
7279
- maxTokens: external_exports.number().optional().default(1e4).describe("Maximum number of tokens to return"),
7280
- language: external_exports.string().optional().describe("Limit search to files of a specific programming language")
7268
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
7269
+ path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
7281
7270
  });
7282
7271
  querySchema = external_exports.object({
7283
7272
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
@@ -7286,13 +7275,8 @@ var init_common = __esm({
7286
7275
  allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results")
7287
7276
  });
7288
7277
  extractSchema = external_exports.object({
7289
- targets: external_exports.string().optional().describe("File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets"),
7290
- input_content: external_exports.string().optional().describe("Text content to extract file paths from"),
7291
- line: external_exports.number().optional().describe("Start line number to extract a specific code block"),
7292
- end_line: external_exports.number().optional().describe("End line number for extracting a range of lines"),
7293
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files and test code blocks"),
7294
- context_lines: external_exports.number().optional().default(10).describe("Number of context lines to include"),
7295
- format: external_exports.string().optional().default("plain").describe("Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)")
7278
+ targets: external_exports.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
7279
+ input_content: external_exports.string().optional().describe("Text content to extract file paths from (alternative to targets)")
7296
7280
  });
7297
7281
  delegateSchema = external_exports.object({
7298
7282
  task: external_exports.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
@@ -7367,13 +7351,8 @@ You need to focus on main keywords when constructing the query, and always use e
7367
7351
  - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
7368
7352
 
7369
7353
  Parameters:
7370
- - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
7371
- - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
7372
- - allow_tests: (optional, default: false) Allow test files in search results (true/false).
7373
- - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
7374
- - maxResults: (optional) Maximum number of results to return (number).
7375
- - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
7376
- - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
7354
+ - query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
7355
+ - path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
7377
7356
 
7378
7357
  **Workflow:** Always start with search, then use extract for detailed context when needed.
7379
7358
 
@@ -7395,30 +7374,24 @@ User: How to calculate the total amount in the payments module?
7395
7374
  <search>
7396
7375
  <query>calculate AND payment</query>
7397
7376
  <path>src/utils</path>
7398
- <allow_tests>false</allow_tests>
7399
7377
  </search>
7400
7378
 
7401
7379
  User: How do the user authentication and authorization work?
7402
7380
  <search>
7403
- <query>+user and (authentification OR authroization OR authz)</query>
7381
+ <query>+user AND (authentication OR authorization OR authz)</query>
7404
7382
  <path>.</path>
7405
- <allow_tests>true</allow_tests>
7406
- <language>go</language>
7407
7383
  </search>
7408
7384
 
7409
7385
  User: Find all react imports in the project.
7410
7386
  <search>
7411
- <query>import { react }</query>
7387
+ <query>"import" AND "react"</query>
7412
7388
  <path>.</path>
7413
- <exact>true</exact>
7414
- <language>js</language>
7415
7389
  </search>
7416
7390
 
7417
- User: Find how decompoud library works?
7391
+ User: Find how decompound library works?
7418
7392
  <search>
7419
- <query>import { react }</query>
7393
+ <query>decompound</query>
7420
7394
  <path>/dep/rust/decompound</path>
7421
- <language>rust</language>
7422
7395
  </search>
7423
7396
 
7424
7397
  </examples>
@@ -7453,11 +7426,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
7453
7426
  **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
7454
7427
 
7455
7428
  Parameters:
7456
- - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
7457
- For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
7458
- - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
7459
- - end_line: (optional) End line number for extracting a range of lines.
7460
- - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
7429
+ - targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
7430
+ - input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
7431
+
7461
7432
  Usage Example:
7462
7433
 
7463
7434
  <examples>
@@ -7484,9 +7455,7 @@ User: Lets read the whole file
7484
7455
 
7485
7456
  User: Read the first 10 lines of the file
7486
7457
  <extract>
7487
- <targets>src/search/ranking.rs</targets>
7488
- <line>1</line>
7489
- <end_line>10</end_line>
7458
+ <targets>src/search/ranking.rs:1-10</targets>
7490
7459
  </extract>
7491
7460
 
7492
7461
  User: Read file inside the dependency
@@ -49412,9 +49381,7 @@ Examples:
49412
49381
  </search>
49413
49382
 
49414
49383
  <extract>
49415
- <path>src/config.js</path>
49416
- <start_line>15</start_line>
49417
- <end_line>25</end_line>
49384
+ <targets>src/config.js:15-25</targets>
49418
49385
  </extract>
49419
49386
 
49420
49387
  <attempt_completion>
package/build/extract.js CHANGED
@@ -48,7 +48,7 @@ export async function extract(options) {
48
48
  const hasContent = options.content !== undefined && options.content !== null;
49
49
 
50
50
  if (!hasFiles && !hasInputFile && !hasContent) {
51
- throw new Error('Either files array, inputFile, or content must be provided');
51
+ throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
52
52
  }
53
53
 
54
54
  // Get the binary path
@@ -149,18 +149,18 @@ class ProbeServer {
149
149
  },
150
150
  {
151
151
  name: 'extract_code',
152
- description: "Extract code from files. Formats: file.js (whole file), file.js:42 (from line), file.js#functionName (symbol).",
152
+ description: "Extract code blocks from files using tree-sitter AST parsing. Each file path can include optional line numbers or symbol names to extract specific code blocks.",
153
153
  inputSchema: {
154
154
  type: 'object',
155
155
  properties: {
156
156
  path: {
157
157
  type: 'string',
158
- description: 'Absolute path to the project directory',
158
+ description: 'Absolute path to the project root directory (used as working directory for relative file paths)',
159
159
  },
160
160
  files: {
161
161
  type: 'array',
162
162
  items: { type: 'string' },
163
- description: 'Array of file paths with optional line/symbol: ["file.rs:10", "file.rs#func_name"]',
163
+ description: 'Array of file paths to extract from. Formats: "file.js" (entire file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Line numbers and symbols are part of the path string, not separate parameters. Paths can be absolute or relative to the project directory.',
164
164
  }
165
165
  },
166
166
  required: ['path', 'files'],
@@ -199,18 +199,18 @@ class ProbeServer {
199
199
  },
200
200
  {
201
201
  name: 'extract_code',
202
- description: "Extract code from files. Formats: file.js (whole file), file.js:42 (from line), file.js#functionName (symbol).",
202
+ description: "Extract code blocks from files using tree-sitter AST parsing. Each file path can include optional line numbers or symbol names to extract specific code blocks.",
203
203
  inputSchema: {
204
204
  type: 'object',
205
205
  properties: {
206
206
  path: {
207
207
  type: 'string',
208
- description: 'Absolute path to the project directory',
208
+ description: 'Absolute path to the project root directory (used as working directory for relative file paths)',
209
209
  },
210
210
  files: {
211
211
  type: 'array',
212
212
  items: { type: 'string' },
213
- description: 'Array of file paths with optional line/symbol: ["file.rs:10", "file.rs#func_name"]',
213
+ description: 'Array of file paths to extract from. Formats: "file.js" (entire file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Line numbers and symbols are part of the path string, not separate parameters. Paths can be absolute or relative to the project directory.',
214
214
  }
215
215
  },
216
216
  required: ['path', 'files'],
@@ -7,13 +7,8 @@ import { z } from 'zod';
7
7
 
8
8
  // Common schemas for tool parameters (used for internal execution after XML parsing)
9
9
  export const searchSchema = z.object({
10
- query: z.string().describe('Search query with Elasticsearch syntax. Use + for important terms.'),
11
- path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
12
- allow_tests: z.boolean().optional().default(false).describe('Allow test files in search results'),
13
- exact: z.boolean().optional().default(false).describe('Perform exact search without tokenization (case-insensitive)'),
14
- maxResults: z.number().optional().describe('Maximum number of results to return'),
15
- maxTokens: z.number().optional().default(10000).describe('Maximum number of tokens to return'),
16
- language: z.string().optional().describe('Limit search to files of a specific programming language')
10
+ query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
11
+ path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
17
12
  });
18
13
 
19
14
  export const querySchema = z.object({
@@ -24,13 +19,8 @@ export const querySchema = z.object({
24
19
  });
25
20
 
26
21
  export const extractSchema = z.object({
27
- targets: z.string().optional().describe('File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets'),
28
- input_content: z.string().optional().describe('Text content to extract file paths from'),
29
- line: z.number().optional().describe('Start line number to extract a specific code block'),
30
- end_line: z.number().optional().describe('End line number for extracting a range of lines'),
31
- allow_tests: z.boolean().optional().default(false).describe('Allow test files and test code blocks'),
32
- context_lines: z.number().optional().default(10).describe('Number of context lines to include'),
33
- format: z.string().optional().default('plain').describe('Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)')
22
+ targets: z.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
23
+ input_content: z.string().optional().describe('Text content to extract file paths from (alternative to targets)')
34
24
  });
35
25
 
36
26
  export const delegateSchema = z.object({
@@ -120,13 +110,8 @@ You need to focus on main keywords when constructing the query, and always use e
120
110
  - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
121
111
 
122
112
  Parameters:
123
- - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
124
- - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
125
- - allow_tests: (optional, default: false) Allow test files in search results (true/false).
126
- - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
127
- - maxResults: (optional) Maximum number of results to return (number).
128
- - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
129
- - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
113
+ - query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
114
+ - path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
130
115
 
131
116
  **Workflow:** Always start with search, then use extract for detailed context when needed.
132
117
 
@@ -148,30 +133,24 @@ User: How to calculate the total amount in the payments module?
148
133
  <search>
149
134
  <query>calculate AND payment</query>
150
135
  <path>src/utils</path>
151
- <allow_tests>false</allow_tests>
152
136
  </search>
153
137
 
154
138
  User: How do the user authentication and authorization work?
155
139
  <search>
156
- <query>+user and (authentification OR authroization OR authz)</query>
140
+ <query>+user AND (authentication OR authorization OR authz)</query>
157
141
  <path>.</path>
158
- <allow_tests>true</allow_tests>
159
- <language>go</language>
160
142
  </search>
161
143
 
162
144
  User: Find all react imports in the project.
163
145
  <search>
164
- <query>import { react }</query>
146
+ <query>"import" AND "react"</query>
165
147
  <path>.</path>
166
- <exact>true</exact>
167
- <language>js</language>
168
148
  </search>
169
149
 
170
- User: Find how decompoud library works?
150
+ User: Find how decompound library works?
171
151
  <search>
172
- <query>import { react }</query>
152
+ <query>decompound</query>
173
153
  <path>/dep/rust/decompound</path>
174
- <language>rust</language>
175
154
  </search>
176
155
 
177
156
  </examples>
@@ -208,11 +187,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
208
187
  **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
209
188
 
210
189
  Parameters:
211
- - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
212
- For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
213
- - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
214
- - end_line: (optional) End line number for extracting a range of lines.
215
- - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
190
+ - targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
191
+ - input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
192
+
216
193
  Usage Example:
217
194
 
218
195
  <examples>
@@ -239,9 +216,7 @@ User: Lets read the whole file
239
216
 
240
217
  User: Read the first 10 lines of the file
241
218
  <extract>
242
- <targets>src/search/ranking.rs</targets>
243
- <line>1</line>
244
- <end_line>10</end_line>
219
+ <targets>src/search/ranking.rs:1-10</targets>
245
220
  </extract>
246
221
 
247
222
  User: Read file inside the dependency
@@ -349,7 +324,7 @@ export const bashDescription = 'Execute bash commands for system exploration and
349
324
  // Valid tool names that should be parsed as tool calls
350
325
  const DEFAULT_VALID_TOOLS = [
351
326
  'search',
352
- 'query',
327
+ 'query',
353
328
  'extract',
354
329
  'delegate',
355
330
  'listFiles',
@@ -358,6 +333,43 @@ const DEFAULT_VALID_TOOLS = [
358
333
  'attempt_completion'
359
334
  ];
360
335
 
336
+ /**
337
+ * Get valid parameter names for a specific tool from its schema
338
+ * @param {string} toolName - Name of the tool
339
+ * @returns {string[]} - Array of valid parameter names for this tool
340
+ */
341
+ function getValidParamsForTool(toolName) {
342
+ // Map tool names to their schemas
343
+ const schemaMap = {
344
+ search: searchSchema,
345
+ query: querySchema,
346
+ extract: extractSchema,
347
+ delegate: delegateSchema,
348
+ bash: bashSchema,
349
+ attempt_completion: attemptCompletionSchema
350
+ };
351
+
352
+ const schema = schemaMap[toolName];
353
+ if (!schema) {
354
+ // For tools without schema (listFiles, searchFiles, implement), return common params
355
+ // These are the shared params that appear across multiple tools
356
+ return ['path', 'directory', 'pattern', 'recursive', 'includeHidden', 'task', 'files', 'autoCommits', 'result'];
357
+ }
358
+
359
+ // For attempt_completion, it has custom validation, just return 'result'
360
+ if (toolName === 'attempt_completion') {
361
+ return ['result'];
362
+ }
363
+
364
+ // Extract keys from Zod schema
365
+ if (schema && schema._def && schema._def.shape) {
366
+ return Object.keys(schema._def.shape());
367
+ }
368
+
369
+ // Fallback: return empty array if we can't extract schema keys
370
+ return [];
371
+ }
372
+
361
373
  // Simple XML parser helper - safer string-based approach
362
374
  export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
363
375
  // Look for each valid tool name specifically using string search
@@ -387,15 +399,12 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
387
399
 
388
400
  const params = {};
389
401
 
402
+ // Get valid parameters for this specific tool from its schema
403
+ const validParams = getValidParamsForTool(toolName);
404
+
390
405
  // Parse parameters using string-based approach for better safety
391
- // Common parameter names to look for (can be extended as needed)
392
- // Note: includes both camelCase and underscore_case variants to handle inconsistencies
393
- const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
394
- 'max_results', 'maxResults', 'result', 'command', 'description', 'task', 'param', 'pattern',
395
- 'allow_tests', 'exact', 'maxTokens', 'language', 'input_content',
396
- 'context_lines', 'format', 'directory', 'autoCommits', 'files', 'targets'];
397
-
398
- for (const paramName of commonParams) {
406
+ // Only look for parameters that are valid for this specific tool
407
+ for (const paramName of validParams) {
399
408
  const paramOpenTag = `<${paramName}>`;
400
409
  const paramCloseTag = `</${paramName}>`;
401
410
 
@@ -410,7 +419,7 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
410
419
  if (paramCloseIndex === -1) {
411
420
  // Find the next opening tag after this parameter
412
421
  let nextTagIndex = innerContent.length;
413
- for (const nextParam of commonParams) {
422
+ for (const nextParam of validParams) {
414
423
  const nextOpenTag = `<${nextParam}>`;
415
424
  const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
416
425
  if (nextIndex !== -1 && nextIndex < nextTagIndex) {
@@ -28645,7 +28645,7 @@ async function extract(options) {
28645
28645
  const hasInputFile = !!options.inputFile;
28646
28646
  const hasContent = options.content !== void 0 && options.content !== null;
28647
28647
  if (!hasFiles && !hasInputFile && !hasContent) {
28648
- throw new Error("Either files array, inputFile, or content must be provided");
28648
+ throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
28649
28649
  }
28650
28650
  const binaryPath = await getBinaryPath(options.binaryOptions || {});
28651
28651
  const filteredOptions = { ...options };
@@ -32912,6 +32912,27 @@ var init_zod = __esm({
32912
32912
  });
32913
32913
 
32914
32914
  // src/tools/common.js
32915
+ function getValidParamsForTool(toolName) {
32916
+ const schemaMap = {
32917
+ search: searchSchema,
32918
+ query: querySchema,
32919
+ extract: extractSchema,
32920
+ delegate: delegateSchema,
32921
+ bash: bashSchema,
32922
+ attempt_completion: attemptCompletionSchema
32923
+ };
32924
+ const schema = schemaMap[toolName];
32925
+ if (!schema) {
32926
+ return ["path", "directory", "pattern", "recursive", "includeHidden", "task", "files", "autoCommits", "result"];
32927
+ }
32928
+ if (toolName === "attempt_completion") {
32929
+ return ["result"];
32930
+ }
32931
+ if (schema && schema._def && schema._def.shape) {
32932
+ return Object.keys(schema._def.shape());
32933
+ }
32934
+ return [];
32935
+ }
32915
32936
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
32916
32937
  for (const toolName of validTools) {
32917
32938
  const openTag = `<${toolName}>`;
@@ -32930,35 +32951,8 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
32930
32951
  closeIndex
32931
32952
  );
32932
32953
  const params = {};
32933
- const commonParams3 = [
32934
- "query",
32935
- "file_path",
32936
- "line",
32937
- "end_line",
32938
- "path",
32939
- "recursive",
32940
- "includeHidden",
32941
- "max_results",
32942
- "maxResults",
32943
- "result",
32944
- "command",
32945
- "description",
32946
- "task",
32947
- "param",
32948
- "pattern",
32949
- "allow_tests",
32950
- "exact",
32951
- "maxTokens",
32952
- "language",
32953
- "input_content",
32954
- "context_lines",
32955
- "format",
32956
- "directory",
32957
- "autoCommits",
32958
- "files",
32959
- "targets"
32960
- ];
32961
- for (const paramName of commonParams3) {
32954
+ const validParams = getValidParamsForTool(toolName);
32955
+ for (const paramName of validParams) {
32962
32956
  const paramOpenTag = `<${paramName}>`;
32963
32957
  const paramCloseTag = `</${paramName}>`;
32964
32958
  const paramOpenIndex = innerContent.indexOf(paramOpenTag);
@@ -32968,7 +32962,7 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
32968
32962
  let paramCloseIndex = innerContent.indexOf(paramCloseTag, paramOpenIndex + paramOpenTag.length);
32969
32963
  if (paramCloseIndex === -1) {
32970
32964
  let nextTagIndex = innerContent.length;
32971
- for (const nextParam of commonParams3) {
32965
+ for (const nextParam of validParams) {
32972
32966
  const nextOpenTag = `<${nextParam}>`;
32973
32967
  const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
32974
32968
  if (nextIndex !== -1 && nextIndex < nextTagIndex) {
@@ -33030,13 +33024,8 @@ var init_common2 = __esm({
33030
33024
  "use strict";
33031
33025
  init_zod();
33032
33026
  searchSchema = external_exports.object({
33033
- query: external_exports.string().describe("Search query with Elasticsearch syntax. Use + for important terms."),
33034
- path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
33035
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results"),
33036
- exact: external_exports.boolean().optional().default(false).describe("Perform exact search without tokenization (case-insensitive)"),
33037
- maxResults: external_exports.number().optional().describe("Maximum number of results to return"),
33038
- maxTokens: external_exports.number().optional().default(1e4).describe("Maximum number of tokens to return"),
33039
- language: external_exports.string().optional().describe("Limit search to files of a specific programming language")
33027
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
33028
+ path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
33040
33029
  });
33041
33030
  querySchema = external_exports.object({
33042
33031
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
@@ -33045,13 +33034,8 @@ var init_common2 = __esm({
33045
33034
  allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results")
33046
33035
  });
33047
33036
  extractSchema = external_exports.object({
33048
- targets: external_exports.string().optional().describe("File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets"),
33049
- input_content: external_exports.string().optional().describe("Text content to extract file paths from"),
33050
- line: external_exports.number().optional().describe("Start line number to extract a specific code block"),
33051
- end_line: external_exports.number().optional().describe("End line number for extracting a range of lines"),
33052
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files and test code blocks"),
33053
- context_lines: external_exports.number().optional().default(10).describe("Number of context lines to include"),
33054
- format: external_exports.string().optional().default("plain").describe("Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)")
33037
+ targets: external_exports.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
33038
+ input_content: external_exports.string().optional().describe("Text content to extract file paths from (alternative to targets)")
33055
33039
  });
33056
33040
  delegateSchema = external_exports.object({
33057
33041
  task: external_exports.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
@@ -33126,13 +33110,8 @@ You need to focus on main keywords when constructing the query, and always use e
33126
33110
  - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
33127
33111
 
33128
33112
  Parameters:
33129
- - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
33130
- - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
33131
- - allow_tests: (optional, default: false) Allow test files in search results (true/false).
33132
- - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
33133
- - maxResults: (optional) Maximum number of results to return (number).
33134
- - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
33135
- - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
33113
+ - query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
33114
+ - path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
33136
33115
 
33137
33116
  **Workflow:** Always start with search, then use extract for detailed context when needed.
33138
33117
 
@@ -33154,30 +33133,24 @@ User: How to calculate the total amount in the payments module?
33154
33133
  <search>
33155
33134
  <query>calculate AND payment</query>
33156
33135
  <path>src/utils</path>
33157
- <allow_tests>false</allow_tests>
33158
33136
  </search>
33159
33137
 
33160
33138
  User: How do the user authentication and authorization work?
33161
33139
  <search>
33162
- <query>+user and (authentification OR authroization OR authz)</query>
33140
+ <query>+user AND (authentication OR authorization OR authz)</query>
33163
33141
  <path>.</path>
33164
- <allow_tests>true</allow_tests>
33165
- <language>go</language>
33166
33142
  </search>
33167
33143
 
33168
33144
  User: Find all react imports in the project.
33169
33145
  <search>
33170
- <query>import { react }</query>
33146
+ <query>"import" AND "react"</query>
33171
33147
  <path>.</path>
33172
- <exact>true</exact>
33173
- <language>js</language>
33174
33148
  </search>
33175
33149
 
33176
- User: Find how decompoud library works?
33150
+ User: Find how decompound library works?
33177
33151
  <search>
33178
- <query>import { react }</query>
33152
+ <query>decompound</query>
33179
33153
  <path>/dep/rust/decompound</path>
33180
- <language>rust</language>
33181
33154
  </search>
33182
33155
 
33183
33156
  </examples>
@@ -33212,11 +33185,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
33212
33185
  **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
33213
33186
 
33214
33187
  Parameters:
33215
- - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
33216
- For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
33217
- - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
33218
- - end_line: (optional) End line number for extracting a range of lines.
33219
- - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
33188
+ - targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
33189
+ - input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
33190
+
33220
33191
  Usage Example:
33221
33192
 
33222
33193
  <examples>
@@ -33243,9 +33214,7 @@ User: Lets read the whole file
33243
33214
 
33244
33215
  User: Read the first 10 lines of the file
33245
33216
  <extract>
33246
- <targets>src/search/ranking.rs</targets>
33247
- <line>1</line>
33248
- <end_line>10</end_line>
33217
+ <targets>src/search/ranking.rs:1-10</targets>
33249
33218
  </extract>
33250
33219
 
33251
33220
  User: Read file inside the dependency
@@ -74959,9 +74928,7 @@ Examples:
74959
74928
  </search>
74960
74929
 
74961
74930
  <extract>
74962
- <path>src/config.js</path>
74963
- <start_line>15</start_line>
74964
- <end_line>25</end_line>
74931
+ <targets>src/config.js:15-25</targets>
74965
74932
  </extract>
74966
74933
 
74967
74934
  <attempt_completion>
package/cjs/index.cjs CHANGED
@@ -1589,7 +1589,7 @@ async function extract(options) {
1589
1589
  const hasInputFile = !!options.inputFile;
1590
1590
  const hasContent = options.content !== void 0 && options.content !== null;
1591
1591
  if (!hasFiles && !hasInputFile && !hasContent) {
1592
- throw new Error("Either files array, inputFile, or content must be provided");
1592
+ throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
1593
1593
  }
1594
1594
  const binaryPath = await getBinaryPath(options.binaryOptions || {});
1595
1595
  const filteredOptions = { ...options };
@@ -5912,6 +5912,27 @@ var init_zod = __esm({
5912
5912
  });
5913
5913
 
5914
5914
  // src/tools/common.js
5915
+ function getValidParamsForTool(toolName) {
5916
+ const schemaMap = {
5917
+ search: searchSchema,
5918
+ query: querySchema,
5919
+ extract: extractSchema,
5920
+ delegate: delegateSchema,
5921
+ bash: bashSchema,
5922
+ attempt_completion: attemptCompletionSchema
5923
+ };
5924
+ const schema = schemaMap[toolName];
5925
+ if (!schema) {
5926
+ return ["path", "directory", "pattern", "recursive", "includeHidden", "task", "files", "autoCommits", "result"];
5927
+ }
5928
+ if (toolName === "attempt_completion") {
5929
+ return ["result"];
5930
+ }
5931
+ if (schema && schema._def && schema._def.shape) {
5932
+ return Object.keys(schema._def.shape());
5933
+ }
5934
+ return [];
5935
+ }
5915
5936
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
5916
5937
  for (const toolName of validTools) {
5917
5938
  const openTag = `<${toolName}>`;
@@ -5930,35 +5951,8 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
5930
5951
  closeIndex
5931
5952
  );
5932
5953
  const params = {};
5933
- const commonParams3 = [
5934
- "query",
5935
- "file_path",
5936
- "line",
5937
- "end_line",
5938
- "path",
5939
- "recursive",
5940
- "includeHidden",
5941
- "max_results",
5942
- "maxResults",
5943
- "result",
5944
- "command",
5945
- "description",
5946
- "task",
5947
- "param",
5948
- "pattern",
5949
- "allow_tests",
5950
- "exact",
5951
- "maxTokens",
5952
- "language",
5953
- "input_content",
5954
- "context_lines",
5955
- "format",
5956
- "directory",
5957
- "autoCommits",
5958
- "files",
5959
- "targets"
5960
- ];
5961
- for (const paramName of commonParams3) {
5954
+ const validParams = getValidParamsForTool(toolName);
5955
+ for (const paramName of validParams) {
5962
5956
  const paramOpenTag = `<${paramName}>`;
5963
5957
  const paramCloseTag = `</${paramName}>`;
5964
5958
  const paramOpenIndex = innerContent.indexOf(paramOpenTag);
@@ -5968,7 +5962,7 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
5968
5962
  let paramCloseIndex = innerContent.indexOf(paramCloseTag, paramOpenIndex + paramOpenTag.length);
5969
5963
  if (paramCloseIndex === -1) {
5970
5964
  let nextTagIndex = innerContent.length;
5971
- for (const nextParam of commonParams3) {
5965
+ for (const nextParam of validParams) {
5972
5966
  const nextOpenTag = `<${nextParam}>`;
5973
5967
  const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
5974
5968
  if (nextIndex !== -1 && nextIndex < nextTagIndex) {
@@ -6030,13 +6024,8 @@ var init_common = __esm({
6030
6024
  "use strict";
6031
6025
  init_zod();
6032
6026
  searchSchema = external_exports.object({
6033
- query: external_exports.string().describe("Search query with Elasticsearch syntax. Use + for important terms."),
6034
- path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
6035
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results"),
6036
- exact: external_exports.boolean().optional().default(false).describe("Perform exact search without tokenization (case-insensitive)"),
6037
- maxResults: external_exports.number().optional().describe("Maximum number of results to return"),
6038
- maxTokens: external_exports.number().optional().default(1e4).describe("Maximum number of tokens to return"),
6039
- language: external_exports.string().optional().describe("Limit search to files of a specific programming language")
6027
+ query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
6028
+ path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
6040
6029
  });
6041
6030
  querySchema = external_exports.object({
6042
6031
  pattern: external_exports.string().describe("AST pattern to search for. Use $NAME for variable names, $$$PARAMS for parameter lists, etc."),
@@ -6045,13 +6034,8 @@ var init_common = __esm({
6045
6034
  allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files in search results")
6046
6035
  });
6047
6036
  extractSchema = external_exports.object({
6048
- targets: external_exports.string().optional().describe("File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets"),
6049
- input_content: external_exports.string().optional().describe("Text content to extract file paths from"),
6050
- line: external_exports.number().optional().describe("Start line number to extract a specific code block"),
6051
- end_line: external_exports.number().optional().describe("End line number for extracting a range of lines"),
6052
- allow_tests: external_exports.boolean().optional().default(false).describe("Allow test files and test code blocks"),
6053
- context_lines: external_exports.number().optional().default(10).describe("Number of context lines to include"),
6054
- format: external_exports.string().optional().default("plain").describe("Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)")
6037
+ targets: external_exports.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
6038
+ input_content: external_exports.string().optional().describe("Text content to extract file paths from (alternative to targets)")
6055
6039
  });
6056
6040
  delegateSchema = external_exports.object({
6057
6041
  task: external_exports.string().describe("The task to delegate to a subagent. Be specific about what needs to be accomplished.")
@@ -6126,13 +6110,8 @@ You need to focus on main keywords when constructing the query, and always use e
6126
6110
  - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
6127
6111
 
6128
6112
  Parameters:
6129
- - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
6130
- - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
6131
- - allow_tests: (optional, default: false) Allow test files in search results (true/false).
6132
- - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
6133
- - maxResults: (optional) Maximum number of results to return (number).
6134
- - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
6135
- - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
6113
+ - query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
6114
+ - path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
6136
6115
 
6137
6116
  **Workflow:** Always start with search, then use extract for detailed context when needed.
6138
6117
 
@@ -6154,30 +6133,24 @@ User: How to calculate the total amount in the payments module?
6154
6133
  <search>
6155
6134
  <query>calculate AND payment</query>
6156
6135
  <path>src/utils</path>
6157
- <allow_tests>false</allow_tests>
6158
6136
  </search>
6159
6137
 
6160
6138
  User: How do the user authentication and authorization work?
6161
6139
  <search>
6162
- <query>+user and (authentification OR authroization OR authz)</query>
6140
+ <query>+user AND (authentication OR authorization OR authz)</query>
6163
6141
  <path>.</path>
6164
- <allow_tests>true</allow_tests>
6165
- <language>go</language>
6166
6142
  </search>
6167
6143
 
6168
6144
  User: Find all react imports in the project.
6169
6145
  <search>
6170
- <query>import { react }</query>
6146
+ <query>"import" AND "react"</query>
6171
6147
  <path>.</path>
6172
- <exact>true</exact>
6173
- <language>js</language>
6174
6148
  </search>
6175
6149
 
6176
- User: Find how decompoud library works?
6150
+ User: Find how decompound library works?
6177
6151
  <search>
6178
- <query>import { react }</query>
6152
+ <query>decompound</query>
6179
6153
  <path>/dep/rust/decompound</path>
6180
- <language>rust</language>
6181
6154
  </search>
6182
6155
 
6183
6156
  </examples>
@@ -6212,11 +6185,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
6212
6185
  **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
6213
6186
 
6214
6187
  Parameters:
6215
- - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
6216
- For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
6217
- - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
6218
- - end_line: (optional) End line number for extracting a range of lines.
6219
- - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
6188
+ - targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
6189
+ - input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
6190
+
6220
6191
  Usage Example:
6221
6192
 
6222
6193
  <examples>
@@ -6243,9 +6214,7 @@ User: Lets read the whole file
6243
6214
 
6244
6215
  User: Read the first 10 lines of the file
6245
6216
  <extract>
6246
- <targets>src/search/ranking.rs</targets>
6247
- <line>1</line>
6248
- <end_line>10</end_line>
6217
+ <targets>src/search/ranking.rs:1-10</targets>
6249
6218
  </extract>
6250
6219
 
6251
6220
  User: Read file inside the dependency
@@ -75136,9 +75105,7 @@ Examples:
75136
75105
  </search>
75137
75106
 
75138
75107
  <extract>
75139
- <path>src/config.js</path>
75140
- <start_line>15</start_line>
75141
- <end_line>25</end_line>
75108
+ <targets>src/config.js:15-25</targets>
75142
75109
  </extract>
75143
75110
 
75144
75111
  <attempt_completion>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc148",
3
+ "version": "0.6.0-rc149",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -920,9 +920,7 @@ Examples:
920
920
  </search>
921
921
 
922
922
  <extract>
923
- <path>src/config.js</path>
924
- <start_line>15</start_line>
925
- <end_line>25</end_line>
923
+ <targets>src/config.js:15-25</targets>
926
924
  </extract>
927
925
 
928
926
  <attempt_completion>
package/src/extract.js CHANGED
@@ -48,7 +48,7 @@ export async function extract(options) {
48
48
  const hasContent = options.content !== undefined && options.content !== null;
49
49
 
50
50
  if (!hasFiles && !hasInputFile && !hasContent) {
51
- throw new Error('Either files array, inputFile, or content must be provided');
51
+ throw new Error('Extract requires one of: "files" (array of file paths), "inputFile" (path to input file), or "content" (string/buffer for stdin)');
52
52
  }
53
53
 
54
54
  // Get the binary path
package/src/mcp/index.ts CHANGED
@@ -199,18 +199,18 @@ class ProbeServer {
199
199
  },
200
200
  {
201
201
  name: 'extract_code',
202
- description: "Extract code from files. Formats: file.js (whole file), file.js:42 (from line), file.js#functionName (symbol).",
202
+ description: "Extract code blocks from files using tree-sitter AST parsing. Each file path can include optional line numbers or symbol names to extract specific code blocks.",
203
203
  inputSchema: {
204
204
  type: 'object',
205
205
  properties: {
206
206
  path: {
207
207
  type: 'string',
208
- description: 'Absolute path to the project directory',
208
+ description: 'Absolute path to the project root directory (used as working directory for relative file paths)',
209
209
  },
210
210
  files: {
211
211
  type: 'array',
212
212
  items: { type: 'string' },
213
- description: 'Array of file paths with optional line/symbol: ["file.rs:10", "file.rs#func_name"]',
213
+ description: 'Array of file paths to extract from. Formats: "file.js" (entire file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Line numbers and symbols are part of the path string, not separate parameters. Paths can be absolute or relative to the project directory.',
214
214
  }
215
215
  },
216
216
  required: ['path', 'files'],
@@ -7,13 +7,8 @@ import { z } from 'zod';
7
7
 
8
8
  // Common schemas for tool parameters (used for internal execution after XML parsing)
9
9
  export const searchSchema = z.object({
10
- query: z.string().describe('Search query with Elasticsearch syntax. Use + for important terms.'),
11
- path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
12
- allow_tests: z.boolean().optional().default(false).describe('Allow test files in search results'),
13
- exact: z.boolean().optional().default(false).describe('Perform exact search without tokenization (case-insensitive)'),
14
- maxResults: z.number().optional().describe('Maximum number of results to return'),
15
- maxTokens: z.number().optional().default(10000).describe('Maximum number of tokens to return'),
16
- language: z.string().optional().describe('Limit search to files of a specific programming language')
10
+ query: z.string().describe('Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation.'),
11
+ path: z.string().optional().default('.').describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
17
12
  });
18
13
 
19
14
  export const querySchema = z.object({
@@ -24,13 +19,8 @@ export const querySchema = z.object({
24
19
  });
25
20
 
26
21
  export const extractSchema = z.object({
27
- targets: z.string().optional().describe('File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets'),
28
- input_content: z.string().optional().describe('Text content to extract file paths from'),
29
- line: z.number().optional().describe('Start line number to extract a specific code block'),
30
- end_line: z.number().optional().describe('End line number for extracting a range of lines'),
31
- allow_tests: z.boolean().optional().default(false).describe('Allow test files and test code blocks'),
32
- context_lines: z.number().optional().default(10).describe('Number of context lines to include'),
33
- format: z.string().optional().default('plain').describe('Output format (plain, markdown, json, xml, color, outline-xml, outline-diff)')
22
+ targets: z.string().optional().describe('File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (symbol). Multiple targets separated by spaces.'),
23
+ input_content: z.string().optional().describe('Text content to extract file paths from (alternative to targets)')
34
24
  });
35
25
 
36
26
  export const delegateSchema = z.object({
@@ -120,13 +110,8 @@ You need to focus on main keywords when constructing the query, and always use e
120
110
  - Once data is returned, it's cached and won't return on next runs (this is expected behavior)
121
111
 
122
112
  Parameters:
123
- - query: (required) Search query with Elasticsearch syntax. You can use + for important terms, and - for negation.
124
- - path: (required) Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc. YOU SHOULD ALWAYS provide FULL PATH when searching dependencies, including depency name.
125
- - allow_tests: (optional, default: false) Allow test files in search results (true/false).
126
- - exact: (optional, default: false) Perform exact pricise search. Use it when you already know function or struct name, or some other code block, and want exact match.
127
- - maxResults: (optional) Maximum number of results to return (number).
128
- - maxTokens: (optional, default: 10000) Maximum number of tokens to return (number).
129
- - language: (optional) Limit search to files of a specific programming language (e.g., 'rust', 'js', 'python', 'go' etc.).
113
+ - query: (required) Search query with Elasticsearch syntax. Use quotes for exact matches ("functionName"), AND/OR for boolean logic, - for negation, + for important terms.
114
+ - path: (optional, default: '.') Path to search in. All dependencies located in /dep folder, under language sub folders, like this: "/dep/go/github.com/owner/repo", "/dep/js/package_name", or "/dep/rust/cargo_name" etc.
130
115
 
131
116
  **Workflow:** Always start with search, then use extract for detailed context when needed.
132
117
 
@@ -148,30 +133,24 @@ User: How to calculate the total amount in the payments module?
148
133
  <search>
149
134
  <query>calculate AND payment</query>
150
135
  <path>src/utils</path>
151
- <allow_tests>false</allow_tests>
152
136
  </search>
153
137
 
154
138
  User: How do the user authentication and authorization work?
155
139
  <search>
156
- <query>+user and (authentification OR authroization OR authz)</query>
140
+ <query>+user AND (authentication OR authorization OR authz)</query>
157
141
  <path>.</path>
158
- <allow_tests>true</allow_tests>
159
- <language>go</language>
160
142
  </search>
161
143
 
162
144
  User: Find all react imports in the project.
163
145
  <search>
164
- <query>import { react }</query>
146
+ <query>"import" AND "react"</query>
165
147
  <path>.</path>
166
- <exact>true</exact>
167
- <language>js</language>
168
148
  </search>
169
149
 
170
- User: Find how decompoud library works?
150
+ User: Find how decompound library works?
171
151
  <search>
172
- <query>import { react }</query>
152
+ <query>decompound</query>
173
153
  <path>/dep/rust/decompound</path>
174
- <language>rust</language>
175
154
  </search>
176
155
 
177
156
  </examples>
@@ -208,11 +187,9 @@ Full file extraction should be the LAST RESORT! Always prefer search.
208
187
  **Session Awareness:** Reuse context from previous tool calls. Don't re-extract the same symbols you already have.
209
188
 
210
189
  Parameters:
211
- - targets: (required) File paths or symbols to extract from. Can include line numbers, symbol names, or multiple space-separated targets (e.g., 'src/main.rs:10-20', 'src/utils.js#myFunction').
212
- For multiple extractions: 'session.rs#AuthService.login auth.rs:2-100 config.rs#DatabaseConfig'
213
- - line: (optional) Start line number to extract a specific code block. Use with end_line for ranges.
214
- - end_line: (optional) End line number for extracting a range of lines.
215
- - allow_tests: (optional, default: false) Allow test files and test code blocks (true/false).
190
+ - targets: (required) File paths or symbols to extract from. Formats: "file.js" (whole file), "file.js:42" (code block at line 42), "file.js:10-20" (lines 10-20), "file.js#funcName" (specific symbol). Multiple targets separated by spaces.
191
+ - input_content: (optional) Text content to extract file paths from (alternative to targets for processing diffs/logs).
192
+
216
193
  Usage Example:
217
194
 
218
195
  <examples>
@@ -239,9 +216,7 @@ User: Lets read the whole file
239
216
 
240
217
  User: Read the first 10 lines of the file
241
218
  <extract>
242
- <targets>src/search/ranking.rs</targets>
243
- <line>1</line>
244
- <end_line>10</end_line>
219
+ <targets>src/search/ranking.rs:1-10</targets>
245
220
  </extract>
246
221
 
247
222
  User: Read file inside the dependency
@@ -349,7 +324,7 @@ export const bashDescription = 'Execute bash commands for system exploration and
349
324
  // Valid tool names that should be parsed as tool calls
350
325
  const DEFAULT_VALID_TOOLS = [
351
326
  'search',
352
- 'query',
327
+ 'query',
353
328
  'extract',
354
329
  'delegate',
355
330
  'listFiles',
@@ -358,6 +333,43 @@ const DEFAULT_VALID_TOOLS = [
358
333
  'attempt_completion'
359
334
  ];
360
335
 
336
+ /**
337
+ * Get valid parameter names for a specific tool from its schema
338
+ * @param {string} toolName - Name of the tool
339
+ * @returns {string[]} - Array of valid parameter names for this tool
340
+ */
341
+ function getValidParamsForTool(toolName) {
342
+ // Map tool names to their schemas
343
+ const schemaMap = {
344
+ search: searchSchema,
345
+ query: querySchema,
346
+ extract: extractSchema,
347
+ delegate: delegateSchema,
348
+ bash: bashSchema,
349
+ attempt_completion: attemptCompletionSchema
350
+ };
351
+
352
+ const schema = schemaMap[toolName];
353
+ if (!schema) {
354
+ // For tools without schema (listFiles, searchFiles, implement), return common params
355
+ // These are the shared params that appear across multiple tools
356
+ return ['path', 'directory', 'pattern', 'recursive', 'includeHidden', 'task', 'files', 'autoCommits', 'result'];
357
+ }
358
+
359
+ // For attempt_completion, it has custom validation, just return 'result'
360
+ if (toolName === 'attempt_completion') {
361
+ return ['result'];
362
+ }
363
+
364
+ // Extract keys from Zod schema
365
+ if (schema && schema._def && schema._def.shape) {
366
+ return Object.keys(schema._def.shape());
367
+ }
368
+
369
+ // Fallback: return empty array if we can't extract schema keys
370
+ return [];
371
+ }
372
+
361
373
  // Simple XML parser helper - safer string-based approach
362
374
  export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
363
375
  // Look for each valid tool name specifically using string search
@@ -387,15 +399,12 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
387
399
 
388
400
  const params = {};
389
401
 
402
+ // Get valid parameters for this specific tool from its schema
403
+ const validParams = getValidParamsForTool(toolName);
404
+
390
405
  // Parse parameters using string-based approach for better safety
391
- // Common parameter names to look for (can be extended as needed)
392
- // Note: includes both camelCase and underscore_case variants to handle inconsistencies
393
- const commonParams = ['query', 'file_path', 'line', 'end_line', 'path', 'recursive', 'includeHidden',
394
- 'max_results', 'maxResults', 'result', 'command', 'description', 'task', 'param', 'pattern',
395
- 'allow_tests', 'exact', 'maxTokens', 'language', 'input_content',
396
- 'context_lines', 'format', 'directory', 'autoCommits', 'files', 'targets'];
397
-
398
- for (const paramName of commonParams) {
406
+ // Only look for parameters that are valid for this specific tool
407
+ for (const paramName of validParams) {
399
408
  const paramOpenTag = `<${paramName}>`;
400
409
  const paramCloseTag = `</${paramName}>`;
401
410
 
@@ -410,7 +419,7 @@ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
410
419
  if (paramCloseIndex === -1) {
411
420
  // Find the next opening tag after this parameter
412
421
  let nextTagIndex = innerContent.length;
413
- for (const nextParam of commonParams) {
422
+ for (const nextParam of validParams) {
414
423
  const nextOpenTag = `<${nextParam}>`;
415
424
  const nextIndex = innerContent.indexOf(nextOpenTag, paramOpenIndex + paramOpenTag.length);
416
425
  if (nextIndex !== -1 && nextIndex < nextTagIndex) {