From 448b40e953ae64aebe56fc9873bf98cf7acd166c Mon Sep 17 00:00:00 2001 From: Overide Date: Sun, 11 May 2025 08:49:39 +0530 Subject: [PATCH] Rollback: Embedding and DepGraph support --- .changeset/hungry-sheep-bathe.md | 5 + src/commands/command.config.ts | 101 +----- src/commands/command.init.ts | 10 +- src/commands/command.start.ts | 22 +- src/models/model.depgraph.ts | 36 -- src/models/model.language.map.ts | 12 - src/services/service.dev.ts | 25 -- src/services/service.embedding.ts | 110 ------ src/services/service.network.ts | 34 -- src/services/service.parser.ts | 323 ------------------ .../service.prompts/service.system.prompt.ts | 46 +-- .../service.prompts/service.user.prompt.ts | 11 - src/utilis/util.command.config.ts | 33 -- src/utilis/util.parser.ts | 118 ------- 14 files changed, 12 insertions(+), 874 deletions(-) create mode 100644 .changeset/hungry-sheep-bathe.md delete mode 100644 src/models/model.depgraph.ts delete mode 100644 src/models/model.language.map.ts delete mode 100644 src/services/service.embedding.ts delete mode 100644 src/services/service.parser.ts diff --git a/.changeset/hungry-sheep-bathe.md b/.changeset/hungry-sheep-bathe.md new file mode 100644 index 0000000..bb8dd90 --- /dev/null +++ b/.changeset/hungry-sheep-bathe.md @@ -0,0 +1,5 @@ +--- +"overide": minor +--- + +Rollback: Embeddings and Dependency graph support. diff --git a/src/commands/command.config.ts b/src/commands/command.config.ts index 1c2dc50..b150f58 100644 --- a/src/commands/command.config.ts +++ b/src/commands/command.config.ts @@ -1,6 +1,3 @@ -import fs from 'fs'; -import path from 'path'; - import { ConfigOption } from '../models/model.options'; import { GlobalConfig, @@ -12,7 +9,6 @@ import CommandHelper from '../utilis/util.command.config'; import OiCommand from './abstract.command'; import { Command } from 'commander'; import inquirer, { Question } from 'inquirer'; -import serviceParser from '../services/service.parser'; import utilParser from '../utilis/util.parser'; /** @@ -50,22 +46,17 @@ class Config extends OiCommand { .command('local') .description('Local configuration options') .option('-i, --ignore ', 'Ignore specific files or directories') - .option('-p, --parse', 'Creates dependency graph for the project') .option('-n, --name ', 'Set project name'); const globalConfig = configCommand .command('global') // Sub-command for global configuration .description('Global configuration options') - .option('-p, --platform', 'Set global variable like API keys and org IDs') - .option('-a, --set-active', 'Select active platform'); + .option('-p, --platform', 'Set global variable like API keys and org IDs'); configCommand.action(async options => { if (Object.keys(options).length === 0) { configCommand.outputHelp(); } - if (options.embedding) { - this.handleEmbeddingEnable(); - } }); localConfig.action(async options => { @@ -75,13 +66,7 @@ class Config extends OiCommand { if (Object.keys(options).length === 0) { localConfig.outputHelp(); } else { - if (options.parse) { - await this.generateDependencyGraph(options.verbose); - } else if (options.graph) { - this.handleDepGraphEnable(); - } else { - await this.handleLocalConfig(options); - } + await this.handleLocalConfig(options); } }); @@ -95,77 +80,9 @@ class Config extends OiCommand { if (options.platform) { await this.handleAddActivePlatform(); } - if (options.setActive) { - await this.handleChangeActivePlatform(); - } }); } - async handleDepGraphEnable(): Promise { - // Set the embeddings flag to true. - this.handleLocalConfig({}, true); - return; - } - - async handleEmbeddingEnable(): Promise { - // Check if OpenAI platform details are available. - const activePlatform = CommandHelper.getActiveServiceDetails(true); - if (!activePlatform) { - console.warn( - 'Overide supports embeddings over OpenAI\nEnabling this will incur additional cost' - ); - // Ask for OpenAI platform details. - const answers = await this.promptPlatformConfig('openai'); - - // Check if a global config file already exists, if not initialize an empty config - const existingConfig = CommandHelper.configExists(true) - ? CommandHelper.readConfigFileData(true) - : {}; - - // Merge the new platform configuration with the existing config - const updatedConfig = { - ...existingConfig, - ['openai']: { - ...answers, - isActive: true // OpenAI is always active for embeddings - } - }; - - // Save the updated global configuration - CommandHelper.writeConfigFileData(true, updatedConfig); - } - - // Set the embeddings flag to true. - this.handleLocalConfig({}, true); - return; - } - - async generateDependencyGraph(verbose: boolean = false): Promise { - try { - // Get the current directory - const currentDir = process.cwd(); - - // Get the ignore list from the oi-config.json file - const config: LocalConfig = CommandHelper.readConfigFileData() as LocalConfig; - const ignoreList = config.ignore || []; - - // Generate dependency graphs for all files in the current directory - const dependencyGraphs = await serviceParser.makeProjectDepGraph( - currentDir, - ignoreList, - verbose - ); - - // Write the dependency graphs to a file - fs.writeFileSync( - path.join(currentDir, 'oi-dependency.json'), - JSON.stringify(dependencyGraphs, null, 2) - ); - } catch (error) { - console.error('Failed to generate dependency graph:', error); - } - } - // Method to handle switching the active platform async handleChangeActivePlatform(): Promise { // Get the global config file path @@ -264,7 +181,7 @@ class Config extends OiCommand { } // Handle the local configuration for the project - async handleLocalConfig(options: ConfigOption, embedding: boolean = false): Promise { + async handleLocalConfig(options: ConfigOption): Promise { // Get the path to the local configuration file // const configFilePath = CommandHelper.getConfigFilePath(); @@ -276,13 +193,6 @@ class Config extends OiCommand { process.exit(1); // Exit if the local config is not found } - if (!CommandHelper.dependencyFileExists()) { - console.error( - 'Dependency file (oi-dependency.json) not found. Run `overide init` to initialize the project.' - ); - process.exit(1); // Exit if the dependency file is not found - } - // Read the local configuration const config: LocalConfig = CommandHelper.readConfigFileData() as LocalConfig; @@ -308,11 +218,6 @@ class Config extends OiCommand { config.projectName = options.name; } - if (embedding) { - console.log('Embedding support for project enabled.'); - config.embedding = true; - } - // Save the updated local configuration CommandHelper.writeConfigFileData(false, config); console.log('Local config updated successfully.'); diff --git a/src/commands/command.init.ts b/src/commands/command.init.ts index 7189aad..49c34f6 100644 --- a/src/commands/command.init.ts +++ b/src/commands/command.init.ts @@ -48,10 +48,9 @@ class Initialize extends OiCommand { console.log('Overide Project initialized!'); console.log('\nNext steps:'); console.log( - "1. Use 'overide config global -p | --platform' to define the API KEYs, BASE URLs and Platforms" + "1. Use 'overide config global -p | --platform' to define the API KEYs, & BASE URLs" ); console.log("2. Run 'overide start' to start getting code suggestions."); - console.log("3. Run 'overide config -e' to enable embeddings based context."); } /** @@ -72,7 +71,6 @@ class Initialize extends OiCommand { outputPath = path.join(process.cwd(), 'oi-config.json'); } - const dependencyFilePath = path.join(options.path ?? process.cwd(), 'oi-dependency.json'); const ignoreFiles = options.ignore || []; const verbose = options.verbose || false; const projectName = options.projectName || 'default-project'; @@ -89,7 +87,6 @@ class Initialize extends OiCommand { // Default ignore files, including config and dependency files, and common directories const defaultIgnoreFiles = [ 'oi-config.json', - 'oi-dependency.json', '/(^|[/\\])../', 'node_modules', '*.swp', @@ -124,11 +121,6 @@ class Initialize extends OiCommand { console.log(`Project initialized with config at ${outputPath}`); } - if (!fs.existsSync(dependencyFilePath)) { - fs.writeFileSync(dependencyFilePath, JSON.stringify([], null, 2)); - console.log(`Project initialized with dependency file at ${dependencyFilePath}`); - } - // Display ASCII art and instructions after initialization this.displayAsciiArt(); } catch (error) { diff --git a/src/commands/command.start.ts b/src/commands/command.start.ts index 50cc834..d415eb2 100644 --- a/src/commands/command.start.ts +++ b/src/commands/command.start.ts @@ -5,9 +5,6 @@ import startCommandHandlerImpl from '../handlers/handler.start'; import { StartOption } from '../models/model.options'; import { LocalConfig } from '../models/model.config'; -import { DependencyGraph } from '../models/model.depgraph'; -import serviceParser from '../services/service.parser'; -import utilParser from '../utilis/util.parser'; /** * The `Start` class extends `OiCommand` and is responsible for initiating @@ -22,7 +19,6 @@ import utilParser from '../utilis/util.parser'; */ class Start extends OiCommand { // Stores the contents of all files in the project - private dependencyGraph: DependencyGraph[] | null = []; private watcher: FSWatcher | null = null; /** @@ -36,13 +32,7 @@ class Start extends OiCommand { .description('Start watching files for prompt changes'); this.addCommonOptions(startCommand); // Add common options such as --verbose - startCommand.action((options: StartOption) => { - // Load the dependency graph from the oi-dependency.json file - this.dependencyGraph = configCommandUtil.loadDependencyGraph(options.path) as - | DependencyGraph[] - | null; - this.startWatch(options); - }); + startCommand.action((options: StartOption) => this.startWatch(options)); } /** @@ -106,16 +96,6 @@ class Start extends OiCommand { console.log(`File ${filePath} has been changed`); } - // Set the dep graph to false if project language is not supported. - const language = utilParser.identifyLanguageByExtension(filePath); - if (language) { - utilParser.loadParserForLanguage(language); // Check if the dependency graph is empty - await serviceParser.makeProjectDepGraphInc(filePath, ignoreFiles, verbose); - if (verbose) { - console.log('Dependency graph updated...'); - } - } - await startCommandHandlerImpl.findPromptInFile(filePath, verbose); } diff --git a/src/models/model.depgraph.ts b/src/models/model.depgraph.ts deleted file mode 100644 index 8b9f8c9..0000000 --- a/src/models/model.depgraph.ts +++ /dev/null @@ -1,36 +0,0 @@ -export type FileContents = { - [filePath: string]: string; -}; - -// Define types for capturing class structure -export interface FunctionData { - class: string; - code: string; - embeddings?: number[]; // The embedding can be optional. -} - -export interface ClassData { - className: string; - embeddings?: number[]; // The embedding can be optional. -} - -export interface GlobalData { - code: string; - embeddings?: number[]; -} - -export interface DependencyGraph { - fileName: string; - path: string; - imports: string[]; - globals: GlobalData[]; - classes: ClassData[]; - functions: FunctionData[]; // Adding a separate array for top-level functions -} - -export interface LanguagePatterns { - language: string; - functionRegex: RegExp; - classRegex: RegExp; - importRegex?: RegExp; -} diff --git a/src/models/model.language.map.ts b/src/models/model.language.map.ts deleted file mode 100644 index 7c3e97d..0000000 --- a/src/models/model.language.map.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Mapping of file extensions to programming languages -export const extensionToLanguageMap: { [extension: string]: string } = { - '.js': 'javascript', - '.ts': 'typescript', - '.py': 'python', - '.java': 'java', - '.cpp': 'c_cpp', - '.cs': 'c_sharp', - '.rb': 'ruby', - '.go': 'go', - '.c': 'c' -}; diff --git a/src/services/service.dev.ts b/src/services/service.dev.ts index 263f66c..c33a29b 100644 --- a/src/services/service.dev.ts +++ b/src/services/service.dev.ts @@ -15,31 +15,6 @@ abstract class DevService { } class DevServiceImpl extends DevService { - /** - * Extracts a code block from the content based on a specific format. - * - * @param content - The content to extract the code block from. - * @param verbose - If true, logs the extracted block. - * @returns The extracted code block. - * @throws Error if no code block is found. - */ - extractCodeBlock(content: string, verbose: boolean = false): ReplacementBlock[] { - console.log(content); - const codeMatch = content.match(/```[\s\S]*?\n([\s\S]*?)\n```/); - if (codeMatch && codeMatch[1]) { - if (verbose) { - console.log(`Extracted Code Block: ${codeMatch[1]}`); - } - try { - return JSON.parse(codeMatch[1]) as ReplacementBlock[]; - } catch (err) { - throw new Error(`No valid JSON found in response ${(err as Error).message}`); - } - } else { - throw new Error('No code block found in the response'); - } - } - /** * Finds the index of the old block in the file content using a flexible matching approach. * diff --git a/src/services/service.embedding.ts b/src/services/service.embedding.ts deleted file mode 100644 index a30a980..0000000 --- a/src/services/service.embedding.ts +++ /dev/null @@ -1,110 +0,0 @@ -import CommandHelper from '../utilis/util.command.config'; -import { ActivePlatformDetails } from '../models/model.config'; -import { DependencyGraph } from '../models/model.depgraph'; -import serviceNetwork from './service.network'; -import serviceDev from './service.dev'; - -abstract class EmbeddingService {} - -class EmbeddingServiceImpl extends EmbeddingService { - /** - * Generates Embeddings for the given dependency graph. - * - * @param graph - The dependency graph node. - * @param embeddingServiceDetails - Platform details for OpenAI. - * @returns - Updated dependency graph node with embeddings. - */ - async getEmbeddingsForDepGraph(graph: DependencyGraph): Promise { - try { - // Is embedding is disabled return the graph without any change. - const isEmbeddingEnabled = CommandHelper.isEmbeddingEnabled(); - if (!isEmbeddingEnabled) { - return graph; - } - - // Get the embedding service detail - const activeServiceDetail: ActivePlatformDetails | null = - CommandHelper.getActiveServiceDetails(true); - - if (!activeServiceDetail) { - console.error('Open AI service details not found!'); - return graph; - } - - // Get the dependency graph. - for (const functions of graph.functions) { - functions.embeddings = await serviceNetwork.getCodeEmbedding( - functions.code, - activeServiceDetail - ); - } - - return graph; - } catch (e) { - if (e instanceof Error) { - console.error(e); - } - return graph; - } - } - - /** - * Generates a contextual prompt and gets embeddings for that. - * - * @param {string} prompt - Prompt entered by the user - * @param fileContent - File contents with the prompt. - * @returns {number[]} - Embeddings for the prompt - */ - async getEmbeddingForPrompt(prompt: string, fileContent: string): Promise { - const platformDetails = CommandHelper.getActiveServiceDetails(true); - - if (!platformDetails) { - return []; - } - - const fileLines = fileContent.split('\n'); - const promptIndex = serviceDev.findMatchingIndex(fileLines, prompt.split('\n')); - const remainingLines = fileLines.length - promptIndex - 1; - let lastIndex = fileLines.length - 1; - - if (remainingLines > 5) { - lastIndex = promptIndex + 5; - } - - const finalPromtArry = []; - - for (let i = promptIndex - 5; i < lastIndex; i++) { - finalPromtArry.push(fileLines[i]); - } - - const promptString = finalPromtArry.join('\n'); - - return await serviceNetwork.getCodeEmbedding(promptString, platformDetails); - } - - /** - * Checks the similarity of two vector embeddings. - * @param vec1 - Embedding prompt - * @param vec2 - Embedding for the functions. - * @returns {number} - Similarity factor. - */ - cosineSimilarity(vec1: number[], vec2: number[]): number { - if (vec1.length !== vec2.length) { - throw new Error('Vectors must be of the same length'); - } - - // Calculate the dot product safely - const dotProduct = vec1.reduce((sum, value, index) => sum + value * vec2[index]!, 0); - - const normVec1 = Math.sqrt(vec1.reduce((sum, value) => sum + value * value, 0)); - const normVec2 = Math.sqrt(vec2.reduce((sum, value) => sum + value * value, 0)); - - if (normVec1 === 0 || normVec2 === 0) { - throw new Error('Vectors must not be zero-vectors'); - } - - return dotProduct / (normVec1 * normVec2); - } -} - -export default new EmbeddingServiceImpl(); diff --git a/src/services/service.network.ts b/src/services/service.network.ts index b169604..6664b1a 100644 --- a/src/services/service.network.ts +++ b/src/services/service.network.ts @@ -8,11 +8,6 @@ import * as dotenv from 'dotenv'; dotenv.config(); abstract class NetworkService { - abstract getCodeEmbedding( - codeSnippet: string, - activeServiceDetails: ActivePlatformDetails - ): Promise; - abstract doRequest(requestData: GeneralRequestObject): Promise; abstract handleOpenAIRequest( @@ -26,35 +21,6 @@ abstract class NetworkService { * to generate code based on the provided request data. */ class NetworkServiceImpl extends NetworkService { - /** - * - * @param codeSnippet - The string code from the dependency graph. - * @param activeServiceDetails - The API key and other metadata. - * @returns {Promise} The generated embedding. - */ - async getCodeEmbedding( - codeSnippet: string, - activeServiceDetails: ActivePlatformDetails - ): Promise { - try { - const { apiKey, orgId } = activeServiceDetails.platformConfig; - const openai = new OpenAI.OpenAI({ apiKey, organization: orgId }); - - // Call the OpenAI API to get embeddings - const response = await openai.embeddings.create({ - model: 'text-embedding-3-small', // Choose the embedding model - input: codeSnippet // The input text (code snippet) - }); - - // Extract the embedding from the response - const embedding = (response.data[0] as OpenAI.Embedding).embedding; // This is an array of numbers - return embedding; - } catch (error) { - console.error('Error fetching embedding:', error); - throw error; - } - } - /** * Generates code based on OpenAI service. * diff --git a/src/services/service.parser.ts b/src/services/service.parser.ts deleted file mode 100644 index de5de9a..0000000 --- a/src/services/service.parser.ts +++ /dev/null @@ -1,323 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -import Parser, { SyntaxNode } from 'tree-sitter'; // Import the Tree-sitter parser -import { ClassData, DependencyGraph, FunctionData, GlobalData } from '../models/model.depgraph'; -import utilParser from '../utilis/util.parser'; -import serviceEmbedding from './service.embedding'; -import utilCommandConfig from '../utilis/util.command.config'; - -abstract class ParserService {} - -// Implementation for ParserService -class ParserServiceImpl extends ParserService { - /** - * Generates a dependency graph for a single file. - * - * @param {string} filePath - The path to the file. - * @param {boolean} verbose - Enable verbose logging. - * @returns {DependencyGraph | null} - The dependency graph for the file or null if processing fails. - */ - async makeFileDepGraph( - filePath: string, - verbose: boolean = false - ): Promise { - const language = utilParser.identifyLanguageByExtension(filePath); - - if (!language) { - if (verbose) console.log(`Language not identified for file: ${filePath}`); - throw new Error('UNSUP_LANG'); - } - - // Load the corresponding Tree-sitter parser for the identified language - let parser: Parser | null = null; - try { - parser = utilParser.loadParserForLanguage(language); - } catch (error) { - if (verbose) { - console.log(`Tree-sitter parser not found or failed to load for ${language}: ${error}`); - } - return null; - } - - if (parser) { - const fileContent = fs.readFileSync(filePath, 'utf8'); - const tree = parser.parse(fileContent); - let depGraph: DependencyGraph = this.extractDepGraphNodeData(filePath, tree); - depGraph = await serviceEmbedding.getEmbeddingsForDepGraph(depGraph); - return depGraph; - } - - return null; - } - - /** - * Generates a dependency graph for all files in a given directory. - * - * @param {string} directory - The root directory for generating dependency graphs. - * @param {string[]} ignoreList - List of file patterns to ignore. - * @param {boolean} verbose - Enable verbose logging. - * @returns {DependencyGraph[]} - Array of dependency graphs for each file. - */ - async makeProjectDepGraph( - directory: string, - ignoreList: string[] = [], - verbose: boolean = false - ): Promise { - const filePaths = utilParser.getAllFilePaths(directory, ignoreList, verbose); - const dependencyGraphs: DependencyGraph[] = []; - - for (const filePath of filePaths) { - const language = utilParser.identifyLanguageByExtension(filePath); - - if (!language) { - if (verbose) console.log(`Language not identified for file: ${filePath}`); - continue; - } - - // Load the corresponding Tree-sitter parser for the identified language - let parser: Parser | null = null; - try { - parser = utilParser.loadParserForLanguage(language); - - if (parser) { - const fileContent = fs.readFileSync(filePath, 'utf8'); - const tree = parser.parse(fileContent); - let dependencyGraph = this.extractDepGraphNodeData(filePath, tree); - dependencyGraph = await serviceEmbedding.getEmbeddingsForDepGraph(dependencyGraph); - dependencyGraphs.push(dependencyGraph); - } - } catch (error) { - if (verbose) { - console.log(`Tree-sitter parser not found or failed to load for ${language} ${error}`); - } - continue; - } - } - - return dependencyGraphs; - } - - /** - * Incrementally updates the `oi-dependency.json` with the dependency graph of a single file. - * - * @param {string} filePath - The path to the file to be incrementally updated. - * @param {boolean} verbose - Enable verbose logging. - */ - async makeProjectDepGraphInc( - filePath: string, - ignoreList: string[], - verbose: boolean = false - ): Promise { - const dependencyFile = 'oi-dependency.json'; - let existingDependencies: DependencyGraph[] = []; - - // Load existing dependency data if the file exists - if (fs.existsSync(dependencyFile)) { - const rawData = fs.readFileSync(dependencyFile, 'utf8'); - existingDependencies = JSON.parse(rawData); - } - - // Check if the file or directory matches any ignore pattern - const shouldIgnore = ignoreList.some(ignorePattern => filePath.includes(ignorePattern)); - - if (shouldIgnore) { - if (verbose) { - console.log(`Skipping ignored path: ${filePath}`); // Log ignored paths if verbose - } - return true; - } - - try { - let newDependencyGraph = await this.makeFileDepGraph(filePath, verbose); - - if (newDependencyGraph) { - const index = existingDependencies.findIndex(dep => dep.path === filePath); - - if (index !== -1) { - // Update existing entry - existingDependencies[index] = newDependencyGraph; - if (verbose) console.log(`Updated dependency graph for file: ${filePath}`); - } else { - // Add new entry - existingDependencies.push(newDependencyGraph); - if (verbose) console.log(`Added new dependency graph for file: ${filePath}`); - } - - // Write updated dependencies back to files - fs.writeFileSync(dependencyFile, JSON.stringify(existingDependencies, null, 2)); - if (verbose) console.log(`Dependency file updated at ${dependencyFile}`); - } else { - if (verbose) console.log(`Failed to generate dependency graph for file: ${filePath}`); - return false; - } - } catch (e) { - if (e instanceof Error && e.message === 'UNSUP_LANG') { - console.error('Overide does not support dependency graph in this language'); - return false; - } - } - - return true; - } - - /** - * Finds the nearest relative node to the given one. - * - * @param filePath The center node for which to find dependency. - * @returns returns the list of nodes (DependencyGraph[]) which are nearest relative. - */ - makeContextFromDepGraph(filePath: string): DependencyGraph[] { - // Load the dependency graph - const depgraph: DependencyGraph[] | null = utilCommandConfig.loadDependencyGraph(); - - if (!depgraph) { - return []; - } - - const adjNodes: DependencyGraph[] = []; - - // Find the current file in dep graph. - let currentNode: DependencyGraph | undefined = depgraph.filter( - node => node.path === filePath - )[0]; - - if (!currentNode) { - return []; - } - - // Get all edges. - for (const importstm of currentNode.imports) { - // Get the fileName from the import. - const importParts = importstm.split('/'); - if (importParts.length === 1) { - continue; - } - const fileName = (importParts[importParts.length - 1] as string) - .replace("'", '') - .replace(';', ''); - - const graphOfImport: DependencyGraph[] | undefined = depgraph.filter(node => - node.path.includes(fileName) - ); - - if (!graphOfImport) { - continue; - } else { - adjNodes.push(...graphOfImport); - } - } - - return adjNodes; - } - - /** - * Extracts dependency information from parsed Tree-sitter tree. - * - * @param {string} filePath - The file path. - * @param {string} fileContent - The file content. - * @param {Parser.Tree} tree - The parsed syntax tree. - * @param {string} language - The language of the file. - * @returns {DependencyGraph} - The dependency graph for the file. - */ - private extractDepGraphNodeData(filePath: string, tree: Parser.Tree): DependencyGraph { - const fileName = path.basename(filePath); - const imports: string[] = []; - const classes: ClassData[] = []; - const globals: GlobalData[] = []; - const functions: FunctionData[] = []; - - const traverseNode = (node: SyntaxNode, currentClass: string | null = null): void => { - // Direct checks for import, class, and function nodes - if (node.isNamed) { - switch (node.type) { - // Combine import statements for different languages - case 'import_statement': - case 'preproc_include': // C/C++ #include - case 'import_from_statement': // Python's `from ... import ...` - case 'require_statement': // Ruby `require ...` - case 'using_directive': // C# `using ...` - imports.push(node.text); - break; - - // Combine class declarations for different languages - case 'class_definition': // Python - case 'class_declaration': // Java, JavaScript, TypeScript, C# - case 'class': // Ruby `class ... end` - case 'struct_declaration': // Go's struct as class - const classData = this.extractClassData(node); - currentClass = classData.className; - classes.push(classData); - break; - - // Combine function declarations for different languages - case 'function_declaration': // JavaScript, TypeScript, Go - case 'method_declaration': // Java, C#, C++ (methods) - case 'function_definition': // C, C++, Go, Python - case 'method_definition': // Ruby methods `def ... end` - functions.push(this.extractFunctionData(node, currentClass)); - break; - - // Global Code (any code outside of classes/functions) - default: - // If node is not part of class or function, it's global code - if ( - node.type === 'expression_statement' && - node.parent && - (node.parent.type === 'program' || node.parent.type === 'module') - ) { - globals.push({ code: node.text }); - } - break; - } - } - - // Recursively process named children - node.namedChildren.forEach(child => traverseNode(child, currentClass)); - }; - - // Begin traversal from the root node - traverseNode(tree.rootNode); - - return { - fileName, - path: filePath, - imports, - globals, - classes, - functions - }; - } - - /** - * Extracts data for a class. - * - * @param {Parser.SyntaxNode} classNode - The class node from Tree-sitter. - * @returns {ClassData} - The extracted class data. - */ - private extractClassData(classNode: Parser.SyntaxNode): ClassData { - const className = classNode.childForFieldName('name')?.text || 'UnnamedClass'; - return { - className, - embeddings: [] - }; - } - - /** - * Extracts data for a function, associating it with its class if provided. - * - * @param {Parser.SyntaxNode} functionNode - The function node. - * @param {string} fileContent - The content of the file. - * @param {string | null} className - The name of the class the function belongs to. - * @returns {FunctionData} - The extracted function data. - */ - private extractFunctionData( - functionNode: Parser.SyntaxNode, - className: string | null - ): FunctionData { - const code = functionNode.text; - return { class: className || '', code, embeddings: [] }; - } -} - -export default new ParserServiceImpl(); diff --git a/src/services/service.prompts/service.system.prompt.ts b/src/services/service.prompts/service.system.prompt.ts index 26fa19d..806ce85 100644 --- a/src/services/service.prompts/service.system.prompt.ts +++ b/src/services/service.prompts/service.system.prompt.ts @@ -8,11 +8,6 @@ import { SystemPromptInfo, SystemPromptPlatformInfo } from '../../models/model.prompts'; -import serviceParser from '../service.parser'; -import { DependencyGraph } from '../../models/model.depgraph'; -import serviceDependency from '../service.embedding'; - -import CommandHelper from '../../utilis/util.command.config'; abstract class SystemPromptService { abstract getOpenAiSystemMessage( @@ -52,10 +47,7 @@ class SystemPromptServiceImpl extends SystemPromptService { // In all the cases load the system prompt const systemPrompt = (this.basePrompt[platform] as SystemPromptPlatformInfo).systemMessage; - const codeContext = this.getCodeContext( - insertionRequest.filePath, - insertionRequest.promptEmbedding ?? [] - ); + const codeContext = this.getCodeContext(insertionRequest.filePath); const instructions = this.getInstructions(platform); let format = ''; @@ -93,44 +85,10 @@ class SystemPromptServiceImpl extends SystemPromptService { * relevant to the user prompt. * @returns A formatted string that includes the first element of contextArray and the user prompt. */ - private getCodeContext(filePath: string, promptEmbd: number[]): string { - const contextGraph: DependencyGraph[] = serviceParser.makeContextFromDepGraph(filePath); + private getCodeContext(filePath: string): string { const contextInformation: string[] = []; - const currentFile = fs.readFileSync(filePath, 'utf-8'); contextInformation.push(currentFile); - - const isEmbeddingEnabled = CommandHelper.isEmbeddingEnabled(); - - for (const node of contextGraph) { - // Add file line - contextInformation.push('File : '); - contextInformation.push(node.path); - - // If there is no functions in the file or Embedding is not enabled. - // It doesn't make sense to just send random function.. rather should - // send the file itself. - if (node.functions.length === 0 || !isEmbeddingEnabled) { - const entireCode = fs.readFileSync(node.path, 'utf-8'); - contextInformation.push(entireCode); - continue; - } - - // Add class and functions - node.functions.forEach(func => { - if (!contextInformation.includes(func.class)) { - contextInformation.push(func.class); - } - - if (isEmbeddingEnabled) { - const similarity = serviceDependency.cosineSimilarity(promptEmbd, func.embeddings ?? []); - if (similarity >= 0.5) { - contextInformation.push(func.code); - } - } - }); - } - return contextInformation.join('\n'); } diff --git a/src/services/service.prompts/service.user.prompt.ts b/src/services/service.prompts/service.user.prompt.ts index 678dbc9..443e943 100644 --- a/src/services/service.prompts/service.user.prompt.ts +++ b/src/services/service.prompts/service.user.prompt.ts @@ -1,7 +1,5 @@ import cacheService from '../../services/service.cache'; import { InsertionRequestInfo, InsertionResponseInfo } from '../../models/model.prompts'; -import serviceEmbedding from '../service.embedding'; -import CommandHelper from '../../utilis/util.command.config'; abstract class UserPromptService { // Regular expressions to match specific prompt types @@ -101,9 +99,6 @@ class UserPromptServiceImpl extends UserPromptService { ): Promise { try { const insertionRequests: InsertionRequestInfo[] = []; - - const isEmbedding = CommandHelper.isEmbeddingEnabled(); - if (verbose) { console.log(`Searching for prompts in ${filePath}`); } @@ -117,12 +112,6 @@ class UserPromptServiceImpl extends UserPromptService { const prompt = match[1].trim(); let promptEmbedding: number[] = []; - if (isEmbedding) { - // Get embedding for current prompt. - promptEmbedding = await serviceEmbedding.getEmbeddingForPrompt(prompt, fileContent); - console.log(promptEmbedding.length); - } - // Add the insertion request to the list insertionRequests.push({ prompt: prompt, diff --git a/src/utilis/util.command.config.ts b/src/utilis/util.command.config.ts index 386c29e..02e0d16 100644 --- a/src/utilis/util.command.config.ts +++ b/src/utilis/util.command.config.ts @@ -7,7 +7,6 @@ import { GlobalPlatformInfo, LocalConfig } from '../models/model.config'; -import { DependencyGraph } from '../models/model.depgraph'; /** * The `DirectoryHelper` class is responsible for managing configuration files and directories @@ -18,33 +17,6 @@ class ConfigCommandUtil { // File names for configuration private static configFileName = 'oi-config.json'; private static globalConfigFileName = 'oi-global-config.json'; - private static dependencyFileName = 'oi-dependency.json'; - - loadDependencyGraph(localPath?: string): DependencyGraph[] | null { - const dependencyFilePath = this.getDependencyFilePath(localPath); - if (fs.existsSync(dependencyFilePath)) { - const dependencyData = fs.readFileSync(dependencyFilePath, 'utf-8'); - const dependencyGraph = JSON.parse(dependencyData); - return dependencyGraph; - } - return null; - } - - /** - * Get the file path for the dependency file. - */ - public getDependencyFilePath(localPath?: string): string { - return path.join(localPath ?? process.cwd(), ConfigCommandUtil.dependencyFileName); - } - - /** - * Checks if the dependency file exists. - * - * @returns {boolean} - True if the dependency file exists, false otherwise. - */ - public dependencyFileExists(): boolean { - return fs.existsSync(this.getDependencyFilePath()); - } /** * Checks if the specified configuration file (local or global) exists. @@ -165,11 +137,6 @@ class ConfigCommandUtil { } } - isEmbeddingEnabled(): boolean { - const localConfig = this.readConfigFileData() as LocalConfig; - return localConfig.embedding; - } - /** * Retrieves the details of the currently active AI service platform. * It reads the global configuration file to determine which platform is marked as active. diff --git a/src/utilis/util.parser.ts b/src/utilis/util.parser.ts index c24ab32..f5597d6 100644 --- a/src/utilis/util.parser.ts +++ b/src/utilis/util.parser.ts @@ -1,83 +1,11 @@ import fs from 'fs'; import path from 'path'; -// Loading the required Tree-sitter language modules -import Java from 'tree-sitter-java'; -import Python from 'tree-sitter-python'; -import Ruby from 'tree-sitter-ruby'; -import Go from 'tree-sitter-go'; -import JavaScript from 'tree-sitter-javascript'; -import TypeScript from 'tree-sitter-typescript'; -import Cpp from 'tree-sitter-cpp'; -import CSharp from 'tree-sitter-c-sharp'; -import C from 'tree-sitter-c'; - -import { extensionToLanguageMap } from '../models/model.language.map'; -import Parser from 'tree-sitter'; -import express from 'express'; - abstract class ParserUtil { abstract getAllFilePaths(directory: string, ignoreList: string[], verbose: boolean): string[]; } class ParserUtilImpl extends ParserUtil { - /** - * Loads a Tree-sitter parser for a given language. - * - * @param {string} language - The language to load. - * @returns {Parser} - The Tree-sitter parser instance for the language. - */ - loadParserForLanguage(language: string): Parser | null { - try { - const parser = new Parser(); - switch (language) { - case 'cpp': - parser.setLanguage(Cpp); - break; - case 'c++': - parser.setLanguage(Cpp); - break; - case 'c': - parser.setLanguage(C); - break; - case 'java': - parser.setLanguage(Java); - break; - case 'python': - parser.setLanguage(Python); - break; - case 'ruby': - parser.setLanguage(Ruby); - break; - case 'go': - parser.setLanguage(Go); - break; - case 'javascript': - parser.setLanguage(JavaScript); - break; - case 'typescript': - parser.setLanguage(TypeScript.typescript); - break; - case 'csharp': - parser.setLanguage(CSharp); - break; - default: - console.log('No Tree-sitter parser found for language:', language); - break; - } - return parser; - } catch (error) { - console.error(`Error loading Tree-sitter parser for ${language}:`, error); - } - return null; - } - - // Identify programming language based on file extension - identifyLanguageByExtension(filePath: string): string | undefined { - const extension = path.extname(filePath); - return extensionToLanguageMap[extension] || undefined; - } - /** * Recursively gathers all file paths in a directory, respecting ignore patterns. * @@ -127,52 +55,6 @@ class ParserUtilImpl extends ParserUtil { return filePaths; } - - // EXPERIMENTAL - /** - * Shows a 3d-visualization of the dependency graph. - * Nothing useful - just a cool thing to have. - */ - async showGraphInSpace(): Promise { - const open = (await import('open')).default; // Dynamic import for ES module - const app = express(); - - // Path to the assets directory (assuming assets are in the root of the project) - const assetsPath = path.join(__dirname, '..', 'assets'); // Go up one level from dist to get to src/assets - - // Serve the graph.html from the assets folder - app.get('/', (req, res) => { - const graphFilePath = path.join(assetsPath, 'graph.html'); - console.log(graphFilePath); - res.sendFile(graphFilePath); - }); - - // Serve static files (like JS, CSS) from the assets folder - app.use(express.static(assetsPath)); - - // Serve the oi-dependency.json from the root directory - app.get('/dependency-graph', (req, res) => { - const dependencyGraphPath = path.join(__dirname, '..', 'oi-dependency.json'); - fs.readFile(dependencyGraphPath, 'utf-8', (err, data) => { - if (err) { - res.status(500).send('Error loading dependency graph'); - return; - } - res.json(JSON.parse(data)); - }); - }); - - // Start the server - const port = 3000; - app.listen(port, () => { - console.log(`Server running at http://localhost:${port}`); - - // Automatically open the browser - open(`http://localhost:${port}`) - .then(() => console.log('Browser opened automatically.')) - .catch(err => console.error('Error opening browser:', err)); - }); - } } export default new ParserUtilImpl();