@probelabs/probe 0.6.0-rc67 → 0.6.0-rc69

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.
@@ -173,52 +173,74 @@ export const searchDescription = 'Search code in the repository using Elasticsea
173
173
  export const queryDescription = 'Search code using ast-grep structural pattern matching. Use this tool to find specific code structures like functions, classes, or methods.';
174
174
  export const extractDescription = 'Extract code blocks from files based on file paths and optional line numbers. Use this tool to see complete context after finding relevant files.';
175
175
 
176
- // Simple XML parser helper
177
- export function parseXmlToolCall(xmlString) {
178
- const toolMatch = xmlString.match(/<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/);
179
- if (!toolMatch) {
180
- return null;
181
- }
176
+ // Valid tool names that should be parsed as tool calls
177
+ const DEFAULT_VALID_TOOLS = [
178
+ 'search',
179
+ 'query',
180
+ 'extract',
181
+ 'listFiles',
182
+ 'searchFiles',
183
+ 'implement',
184
+ 'attempt_completion'
185
+ ];
182
186
 
183
- const toolName = toolMatch[1];
184
- const innerContent = toolMatch[2];
185
- const params = {};
186
-
187
- const paramRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
188
- let paramMatch;
189
- while ((paramMatch = paramRegex.exec(innerContent)) !== null) {
190
- const paramName = paramMatch[1];
191
- let paramValue = paramMatch[2].trim();
192
-
193
- // Basic type inference (can be improved)
194
- if (paramValue.toLowerCase() === 'true') {
195
- paramValue = true;
196
- } else if (paramValue.toLowerCase() === 'false') {
197
- paramValue = false;
198
- } else if (!isNaN(paramValue) && paramValue.trim() !== '') {
199
- // Check if it's potentially a number (handle integers and floats)
200
- const num = Number(paramValue);
201
- if (Number.isFinite(num)) { // Use Number.isFinite to avoid Infinity/NaN
202
- paramValue = num;
203
- }
204
- // Keep as string if not a valid finite number
187
+ // Simple XML parser helper
188
+ export function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
189
+ // Find all potential XML tag matches
190
+ const globalRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
191
+ let match;
192
+
193
+ // Look through all matches to find the first valid tool
194
+ while ((match = globalRegex.exec(xmlString)) !== null) {
195
+ const toolName = match[1];
196
+
197
+ // Only parse XML tags that correspond to valid tools
198
+ if (!validTools.includes(toolName)) {
199
+ continue; // Skip non-tool tags and look for the next match
205
200
  }
206
201
 
207
- params[paramName] = paramValue;
208
- }
202
+ const innerContent = match[2];
203
+ const params = {};
204
+
205
+ const paramRegex = /<([a-zA-Z0-9_]+)>([\s\S]*?)<\/\1>/g;
206
+ let paramMatch;
207
+ while ((paramMatch = paramRegex.exec(innerContent)) !== null) {
208
+ const paramName = paramMatch[1];
209
+ let paramValue = paramMatch[2].trim();
210
+
211
+ // Basic type inference (can be improved)
212
+ if (paramValue.toLowerCase() === 'true') {
213
+ paramValue = true;
214
+ } else if (paramValue.toLowerCase() === 'false') {
215
+ paramValue = false;
216
+ } else if (!isNaN(paramValue) && paramValue.trim() !== '') {
217
+ // Check if it's potentially a number (handle integers and floats)
218
+ const num = Number(paramValue);
219
+ if (Number.isFinite(num)) { // Use Number.isFinite to avoid Infinity/NaN
220
+ paramValue = num;
221
+ }
222
+ // Keep as string if not a valid finite number
223
+ }
209
224
 
210
- // Special handling for attempt_completion where result might contain nested XML/code
211
- if (toolName === 'attempt_completion') {
212
- const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
213
- if (resultMatch) {
214
- params['result'] = resultMatch[1].trim(); // Keep result content as is
225
+ params[paramName] = paramValue;
215
226
  }
216
- const commandMatch = innerContent.match(/<command>([\s\S]*?)<\/command>/);
217
- if (commandMatch) {
218
- params['command'] = commandMatch[1].trim();
227
+
228
+ // Special handling for attempt_completion where result might contain nested XML/code
229
+ if (toolName === 'attempt_completion') {
230
+ const resultMatch = innerContent.match(/<result>([\s\S]*?)<\/result>/);
231
+ if (resultMatch) {
232
+ params['result'] = resultMatch[1].trim(); // Keep result content as is
233
+ }
234
+ const commandMatch = innerContent.match(/<command>([\s\S]*?)<\/command>/);
235
+ if (commandMatch) {
236
+ params['command'] = commandMatch[1].trim();
237
+ }
219
238
  }
220
- }
221
239
 
240
+ // Return the first valid tool found
241
+ return { toolName, params };
242
+ }
222
243
 
223
- return { toolName, params };
244
+ // No valid tool found
245
+ return null;
224
246
  }