import { tool } from 'ai';
import { search } from '../search.js';
import { query } from '../query.js';
import { extract } from '../extract.js';
import { searchSchema, querySchema, extractSchema, searchDescription, queryDescription, extractDescription } from './common.js';
export const searchTool = (options = {}) => {
const { sessionId, maxTokens = 10000, debug = false } = options;
return tool({
name: 'search',
description: searchDescription,
parameters: searchSchema,
execute: async ({ query: searchQuery, path, allow_tests, exact, maxTokens: paramMaxTokens, language }) => {
try {
const effectiveMaxTokens = paramMaxTokens || maxTokens;
let searchPath = path || options.defaultPath || '.';
if ((searchPath === "." || searchPath === "./") && options.defaultPath) {
if (debug) {
console.error(`Using default path "${options.defaultPath}" instead of "${searchPath}"`);
}
searchPath = options.defaultPath;
}
if (debug) {
console.error(`Executing search with query: "${searchQuery}", path: "${searchPath}", exact: ${exact ? 'true' : 'false'}, language: ${language || 'all'}, session: ${sessionId || 'none'}`);
}
const results = await search({
query: searchQuery,
path: searchPath,
allow_tests,
exact,
json: false,
maxTokens: effectiveMaxTokens,
session: sessionId, language });
return results;
} catch (error) {
console.error('Error executing search command:', error);
return `Error executing search command: ${error.message}`;
}
}
});
};
export const queryTool = (options = {}) => {
const { debug = false } = options;
return tool({
name: 'query',
description: queryDescription,
parameters: querySchema,
execute: async ({ pattern, path, language, allow_tests }) => {
try {
let queryPath = path || options.defaultPath || '.';
if ((queryPath === "." || queryPath === "./") && options.defaultPath) {
if (debug) {
console.error(`Using default path "${options.defaultPath}" instead of "${queryPath}"`);
}
queryPath = options.defaultPath;
}
if (debug) {
console.error(`Executing query with pattern: "${pattern}", path: "${queryPath}", language: ${language || 'auto'}`);
}
const results = await query({
pattern,
path: queryPath,
language,
allow_tests,
json: false
});
return results;
} catch (error) {
console.error('Error executing query command:', error);
return `Error executing query command: ${error.message}`;
}
}
});
};
export const extractTool = (options = {}) => {
const { debug = false } = options;
return tool({
name: 'extract',
description: extractDescription,
parameters: extractSchema,
execute: async ({ file_path, input_content, line, end_line, allow_tests, context_lines, format }) => {
try {
let extractPath = options.defaultPath || '.';
if ((extractPath === "." || extractPath === "./") && options.defaultPath) {
if (debug) {
console.error(`Using default path "${options.defaultPath}" instead of "${extractPath}"`);
}
extractPath = options.defaultPath;
}
if (debug) {
if (file_path) {
console.error(`Executing extract with file: "${file_path}", path: "${extractPath}", context lines: ${context_lines || 10}`);
} else if (input_content) {
console.error(`Executing extract with input content, path: "${extractPath}", context lines: ${context_lines || 10}`);
}
}
let tempFilePath = null;
let extractOptions = { path: extractPath };
if (input_content) {
const { writeFileSync, unlinkSync } = await import('fs');
const { join } = await import('path');
const { tmpdir } = await import('os');
const { randomUUID } = await import('crypto');
tempFilePath = join(tmpdir(), `probe-extract-${randomUUID()}.txt`);
writeFileSync(tempFilePath, input_content);
if (debug) {
console.error(`Created temporary file for input content: ${tempFilePath}`);
}
extractOptions = {
inputFile: tempFilePath,
allowTests: allow_tests,
contextLines: context_lines,
format
};
} else if (file_path) {
const files = [file_path];
extractOptions = {
files,
allowTests: allow_tests,
contextLines: context_lines,
format
};
} else {
throw new Error('Either file_path or input_content must be provided');
}
const results = await extract(extractOptions);
if (tempFilePath) {
const { unlinkSync } = await import('fs');
try {
unlinkSync(tempFilePath);
if (debug) {
console.error(`Removed temporary file: ${tempFilePath}`);
}
} catch (cleanupError) {
console.error(`Warning: Failed to remove temporary file: ${cleanupError.message}`);
}
}
return results;
} catch (error) {
console.error('Error executing extract command:', error);
return `Error executing extract command: ${error.message}`;
}
}
});
};