update_file_analysis
Update or create file analysis data including symbols, imports, and exports to keep code summaries accurate.
Instructions
Update or create analysis data for a specific file in the TreeSummary system
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filePath | Yes | Absolute path to the file to analyze or update. Used as the primary key for storing analysis data. | |
| analysisData | Yes | Complete analysis data for the file including symbols, imports, exports, and metadata |
Implementation Reference
- src/tools/TreeSummaryTools.ts:44-51 (registration)Registration of the 'update_file_analysis' MCP tool in the getTools() method, defining its name, description, input/output schemas, and binding to the updateFileAnalysis handler.
return [ { name: "update_file_analysis", description: "Update or create analysis data for a specific file in the TreeSummary system", inputSchema: zodToJsonSchema(UpdateFileAnalysisSchema), outputSchema: zodToJsonSchema(UpdateFileAnalysisResponseSchema), handler: this.updateFileAnalysis.bind(this), - src/tools/TreeSummaryTools.ts:90-135 (handler)The updateFileAnalysis handler method that normalizes snake_case/camelCase args, parses date strings, calls the TreeSummaryService, and returns success/error responses.
private async updateFileAnalysis(args: any): Promise<TreeSummaryResponse> { const startTime = Date.now(); // Map snake_case to camelCase for compatibility const normalizedArgs = { filePath: args.filePath || args.file_path, analysisData: args.analysisData || args.analysis_data }; const { filePath, analysisData } = normalizedArgs; try { // Parse date if it's a string if (typeof analysisData.lastModified === "string") { analysisData.lastModified = new Date(analysisData.lastModified); } const success = await this.treeSummaryService.updateFileAnalysis( filePath, analysisData ); if (success) { return createSuccessResponse( `Successfully updated analysis for ${filePath}`, { file_path: filePath, analysis_updated: true, }, Date.now() - startTime ); } else { return createErrorResponse( `Failed to update analysis for ${filePath}`, "Update operation returned false", "UPDATE_FAILED" ); } } catch (error) { return createErrorResponse( `Error updating analysis for ${filePath}`, error instanceof Error ? error.message : String(error), "UPDATE_ERROR" ); } } - The UpdateFileAnalysisSchema Zod schema defining the input shape: filePath (string) and analysisData (object with filePath, hash, lastModified, symbols, imports, exports, size, language).
export const UpdateFileAnalysisSchema = z.object({ filePath: z.string().describe("Absolute path to the file to analyze or update. Used as the primary key for storing analysis data."), analysisData: z.object({ filePath: z.string().describe("Absolute path to the file (should match the parent filePath parameter)"), hash: z.string().describe("SHA-256 hash of the file content, used to detect changes and avoid unnecessary re-analysis"), lastModified: z.string().describe("ISO 8601 timestamp of when the file was last modified"), symbols: z.array(z.object({ name: z.string().describe("Name of the symbol (function, class, variable, etc.)"), type: z.enum(['function', 'class', 'variable', 'interface', 'type', 'enum']).describe("Type of the symbol found in the code"), line: z.number().describe("Line number where the symbol is defined (1-based)"), column: z.number().describe("Column number where the symbol is defined (1-based)"), accessibility: z.enum(['public', 'private', 'protected']).optional().describe("Accessibility modifier for the symbol (mainly for class members)"), isExported: z.boolean().describe("Whether this symbol is exported from the module") })).describe("Array of all symbols (functions, classes, variables, etc.) found in the file"), imports: z.array(z.string()).describe("Array of all import statements/dependencies used by this file"), exports: z.array(z.string()).describe("Array of all symbols exported by this file"), size: z.number().describe("File size in bytes"), language: z.string().describe("Programming language detected (e.g., 'typescript', 'javascript', 'python')") }).describe("Complete analysis data for the file including symbols, imports, exports, and metadata") }); - The UpdateFileAnalysisResponseSchema Zod schema defining the output shape: success, message, timestamp, execution_time_ms, and data (file_path, analysis_updated).
export const UpdateFileAnalysisResponseSchema = z.object({ success: z.boolean().describe("Whether the file analysis update operation succeeded. True if the file analysis was successfully stored or updated in the TreeSummary database."), message: z.string().describe("Human-readable message describing the result of the operation. Typically 'Successfully updated analysis for [file_path]' on success or an error description on failure."), timestamp: z.string().describe("ISO 8601 timestamp of when the operation completed, automatically generated when the response is created."), execution_time_ms: z.number().optional().describe("Time taken to execute the operation in milliseconds, measured from the start of the operation until completion."), data: z.object({ file_path: z.string().describe("Absolute path to the file that was analyzed. This matches the input filePath parameter."), analysis_updated: z.boolean().describe("Whether the analysis data was successfully updated. Always true for successful operations, indicating the file's symbols, imports, exports, and metadata were stored.") }).optional().describe("Additional data about the operation result. Contains the file path and confirmation that analysis was updated. Only present on successful operations.") }); - The TreeSummaryService.updateFileAnalysis() method: finds project root, invalidates foundation cache, ensures .treesummary directory, writes analysis to .treesummary/files/<relative-path>.json atomically (temp file + rename), and updates project metadata.
async updateFileAnalysis(filePath: string, analysisData: FileAnalysis): Promise<boolean> { try { const projectPath = this.findProjectRoot(filePath); const treeSummaryPath = path.join(projectPath, this.treeSummaryDir); // Invalidate relevant foundation cache entries if (this.foundationCache) { try { // Invalidate project-level caches since file analysis changed await this.foundationCache.invalidateCache({ filePath: projectPath, templateId: 'project_overview' }); } catch (error) { console.warn('Failed to invalidate foundation cache:', error); } } // Ensure .treesummary directory exists await this.ensureTreeSummaryDirectory(treeSummaryPath); // Create atomic file write with directory structure preservation const relativeFilePath = path.relative(projectPath, filePath); // Create clean mirror structure: .treesummary/files/path/to/file.ext.json const analysisFile = path.join(treeSummaryPath, 'files', relativeFilePath + '.json'); // Ensure files directory exists await fs.mkdir(path.dirname(analysisFile), { recursive: true }); // Write to temporary file first for atomic operation const tempFile = analysisFile + '.tmp'; await fs.writeFile(tempFile, JSON.stringify(analysisData, null, 2)); // Atomic rename await fs.rename(tempFile, analysisFile); // Update project metadata await this.updateProjectMetadata(projectPath); return true; } catch (error) { console.error(`Failed to update file analysis for ${filePath}:`, error); return false; } }