From 89470eeafd9a9c1651bc913519e819eae722d46e Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Tue, 28 Jan 2025 22:06:21 -0500 Subject: [PATCH 1/5] change convert json prompt to another json formate --- .../file-manager/file-structure/prompt.ts | 69 +++++++------------ 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts index 5c5e3956..f6fed4ec 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts @@ -15,49 +15,28 @@ export const prompts = { convertTreeToJsonPrompt: (): string => { return `You are a highly skilled developer. Your task is to convert the previous file and folder structure, currently represented in an ASCII tree format, into a JSON structure. The JSON structure must: - - - Represent directories and files in a hierarchical manner. - - Use objects with "type" and "name" keys. - - For directories: - - "type": "directory" - - "name": "" - - "children": [ ... ] (an array of files or directories) - - For files: - - "type": "file" - - "name": "" - - Maintain the same nesting as the original ASCII tree. - - **Output Format:** - Return a JSON object of the form: - \`\`\`json - { - "type": "directory", - "name": "", - "children": [ - { - "type": "directory", - "name": "subDirName", - "children": [ - { - "type": "file", - "name": "fileName.ext" - } - ] - }, - { - "type": "file", - "name": "anotherFile.ext" - } - ] - } - \`\`\` - - **Additional Rules:** - - Keep directory names and file names exactly as they appear (excluding trailing slashes). - - For directories that appear like "common/", in the JSON just use "common" as the name. - - Do not include comments or extra fields besides "type", "name", and "children". - - The root node should correspond to the top-level directory in the tree. - + + Represent all file paths in a flat list under the "Paths" array. + Maintain the full paths for each file exactly as they appear in the ASCII tree. + Directories should not be included—only file paths. + +Output Format: +Return a JSON object in the following format: + +{ + "Paths": [ + "/full/path/to/file1.ext", + "/full/path/to/file2.ext", + "/another/path/to/file3.ext" + ] +} + +Additional Rules: + + Maintain the original directory structure but only return files in the JSON output. + Keep file names and paths exactly as they appear in the ASCII tree. + The root node should correspond to the top-level directory in the tree. + Do not include comments or extra fields besides "Paths". Return only the JSON structure (no explanations, no additional comments). This JSON will be used directly in the application. `; }, @@ -93,12 +72,14 @@ export const prompts = { Asset folders (e.g., images, icons, fonts). Test folders or files. Service folders unrelated to API logic. - Dont need .css files. + .css files. `; fileNamingGuidelines = ` File Naming Guidelines: Use meaningful and descriptive file names. + For components, include an index.tsx file in each folder to simplify imports. Each component should have its own folder named after the component (e.g., Button/). + Use index.tsx as the main file inside the component folder. `; break; From d94e8ba9c601a325b67db167fc2b26206c1d2a84 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 29 Jan 2025 17:33:17 -0500 Subject: [PATCH 2/5] refact to improve file arch --- .../handlers/file-manager/file-arch/index.ts | 32 ++- .../handlers/file-manager/file-arch/prompt.ts | 23 +- .../file-manager/file-structure/index.ts | 44 ++- .../file-manager/file-structure/prompt.ts | 21 +- .../build-system/utils/file_generator_util.ts | 14 +- backend/src/build-system/virtual-dir/index.ts | 256 ++++++++++-------- 6 files changed, 202 insertions(+), 188 deletions(-) diff --git a/backend/src/build-system/handlers/file-manager/file-arch/index.ts b/backend/src/build-system/handlers/file-manager/file-arch/index.ts index 0ff3241b..15a56afa 100644 --- a/backend/src/build-system/handlers/file-manager/file-arch/index.ts +++ b/backend/src/build-system/handlers/file-manager/file-arch/index.ts @@ -14,13 +14,14 @@ import { ModelUnavailableError, } from 'src/build-system/errors'; import { VirtualDirectory } from 'src/build-system/virtual-dir'; + +import { FileStructureHandler } from '../file-structure'; +import { UXDMDHandler } from '../../ux/datamap'; +import { BuildNode, BuildNodeRequire } from 'src/build-system/hanlder-manager'; import { buildDependencyGraph, validateAgainstVirtualDirectory, } from 'src/build-system/utils/file_generator_util'; -import { FileStructureHandler } from '../file-structure'; -import { UXDMDHandler } from '../../ux/datamap'; -import { BuildNode, BuildNodeRequire } from 'src/build-system/hanlder-manager'; @BuildNode() @BuildNodeRequire([FileStructureHandler, UXDMDHandler]) @@ -36,6 +37,7 @@ export class FileFAHandler implements BuildHandler { const fileStructure = context.getNodeData(FileStructureHandler); const datamapDoc = context.getNodeData(UXDMDHandler); + this.logger.log('fileStructure:', fileStructure); if (!fileStructure || !datamapDoc) { throw new InvalidParameterError( 'Missing required parameters: fileStructure or datamapDoc.', @@ -57,7 +59,7 @@ export class FileFAHandler implements BuildHandler { ${datamapDoc} - Next, I'll provide the **Directory Structure**.`, + Next, I will provide the **Directory Structure** to help you understand the full project architecture.`, }, { role: 'user' as const, @@ -67,13 +69,15 @@ export class FileFAHandler implements BuildHandler { ${fileStructure} - Please generate the full File Architecture JSON object now, ensuring adherence to all the rules.`, + Based on this structure and the analysis provided earlier, please generate the File Architecture JSON object. Ensure the output adheres to all rules and guidelines specified in the system prompt.`, }, { role: 'user' as const, - content: `**Final Check:** - - Ensure the JSON structure is correct. - - Ensure all files and dependencies are included.`, + content: `**Final Check** + Before returning the output, ensure the following: + - The JSON structure is correctly formatted and wrapped in tags. + - File extensions and paths match those in the Directory Structure. + - All files and dependencies are included.`, }, ]; @@ -108,11 +112,19 @@ export class FileFAHandler implements BuildHandler { ); } - console.log(jsonData); // validate with virutual dir const { graph, nodes, fileInfos } = buildDependencyGraph(jsonData); - if (!validateAgainstVirtualDirectory(nodes, this.virtualDir)) { + + const invalidFiles = validateAgainstVirtualDirectory( + nodes, + this.virtualDir, + ); + + if (invalidFiles) { this.logger.error('Validate Against Virtual Directory Fail !!!'); + this.logger.error(`Invalid files detected:\n${invalidFiles}`); + this.logger.error(`${fileArchContent}`); + this.logger.error(`${fileStructure}`); throw new ResponseParsingError( 'Failed to validate against virtualDirectory.', ); diff --git a/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts b/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts index 480da7ab..ad8cc233 100644 --- a/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts @@ -4,18 +4,19 @@ export const generateFileArchPrompt = (): string => { ### Instructions 1. **Analyze the Inputs**: - Use the directory structure to identify all files and folders. + - Do not assume any additional files or paths. The structure must be based exclusively on the given list. - Leverage the page-by-page analysis to understand the roles and interactions of different components and pages. - Determine the role of each file based on its path and the provided analysis (e.g., page, component, context, hook, styles). - Identify direct dependencies for each file by considering typical imports based on roles, naming conventions, and the provided analysis. 2. **Generate File Dependency JSON**: + - Each file must be represented using its full path starting from src/. + - Ensure dependencies are strictly limited to files in the "Paths" array. + - Use absolute file paths from "Paths" for all "dependsOn" values. + Do not use relative paths (./, ../). + Every dependency must match exactly one of the files in "Paths". + - Any file without dependencies should have "dependsOn": []. - For each file, list its direct dependencies as an array of relative paths in the \`dependsOn\` field. - - Use relative paths for dependencies whenever possible. For example: - - If a file \`index.tsx\` references a CSS file \`index.css\` in the same folder, the dependency should be listed as \`"./index.css"\`. - - If a file references another file in its parent folder, use \`"../filename"\`. - - Only use absolute paths (e.g., starting with \`src/\`) when no shorter relative path is available. - - Include CSS/SCSS files as dependencies for any JavaScript or TypeScript files that reference them (e.g., through imports or implied usage). - - Include files that have no dependencies with an empty \`dependsOn\` array. - Organize the output in a \`files\` object where keys are file paths, and values are their dependency objects. - For the router, remember to include all the page components as dependencies, as the router imports them to define the application routes. - For the src/index.tsx, remember to include router.ts. @@ -37,16 +38,12 @@ export const generateFileArchPrompt = (): string => { \`\`\` - Keys: Every file must be represented with its full path, starting from src/. - - Dependencies: - Files with no dependencies must have "dependsOn": []. - Every file except src/index.ts must appear in at least one dependsOn array. - - Use relative paths for dependencies wherever possible (./filename for same-folder dependencies, ../filename for parent-folder dependencies). + - Dependency Rules: + All dependencies must exist in the "Paths" array. + No inferred or assumed files should be added. - Wrap the JSON output with \`\` tags. ### Notes -- **CSS Dependencies**: Any file that relies on a CSS/SCSS module file (e.g., \`Header.module.css\`) must list it in the \`dependsOn\` array. -- **Use Relative Paths When Possible**: Ensure dependencies are listed using the shortest possible path (e.g., \`"./filename"\` for files in the same folder). -- **Dependency Inclusion Rule**: All files, except for \`src/index.ts\`, must be depended upon by at least one other file. This means they should appear in the \`dependsOn\` array of at least one other file. - The \`dependsOn\` field should reflect logical dependencies inferred from both the directory structure and the page-by-page analysis. - Use common project patterns to deduce dependencies (e.g., pages depend on components, contexts, hooks, and styles). - Include all files in the output, even if they have no dependencies. diff --git a/backend/src/build-system/handlers/file-manager/file-structure/index.ts b/backend/src/build-system/handlers/file-manager/file-structure/index.ts index ff760500..e36092bc 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/index.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/index.ts @@ -2,7 +2,10 @@ import { BuildHandler, BuildOpts, BuildResult } from 'src/build-system/types'; import { BuilderContext } from 'src/build-system/context'; import { prompts } from './prompt'; import { Logger } from '@nestjs/common'; -import { removeCodeBlockFences } from 'src/build-system/utils/strings'; +import { + parseGenerateTag, + removeCodeBlockFences, +} from 'src/build-system/utils/strings'; import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper'; import { ResponseParsingError, @@ -10,7 +13,6 @@ import { } from 'src/build-system/errors'; import { UXSMDHandler } from '../../ux/sitemap-document'; import { UXDMDHandler } from '../../ux/datamap'; -import { parseGenerateTag } from 'src/build-system/utils/strings'; import { BuildNode, BuildNodeRequire } from 'src/build-system/hanlder-manager'; /** @@ -109,31 +111,7 @@ export class FileStructureHandler implements BuildHandler { return { success: false, error }; } - // Convert the tree structure to JSON - // const convertToJsonPrompt = - // prompts.convertTreeToJsonPrompt(fileStructureContent); - - // let fileStructureJsonContent: string; - // try { - // fileStructureJsonContent = await chatSyncWithClocker( - // context, - // { - // model: 'gpt-4o-mini', - // messages: [{ content: convertToJsonPrompt, role: 'system' }], - // }, - // 'convertToJsonPrompt', - // this.id, - // ); - - // if (!fileStructureJsonContent || fileStructureJsonContent.trim() === '') { - // throw new ResponseParsingError( - // `Generated content is empty during op:FILE:STRUCT 2.`, - // ); - // } - // } catch (error) { - // return { success: false, error }; - // } - + this.logger.log('start parse'); // Build the virtual directory let fileStructureJsonContent = ''; try { @@ -146,13 +124,20 @@ export class FileStructureHandler implements BuildHandler { ), }; } + this.logger.log('parse success: ' + fileStructureJsonContent); + this.logger.log('start building'); try { const successBuild = context.buildVirtualDirectory( fileStructureJsonContent, ); if (!successBuild) { + this.logger.error( + 'Failed to build virtual directory.' + fileStructureJsonContent, + ); throw new ResponseParsingError('Failed to build virtual directory.'); + } else { + this.logger.log('build success'); } } catch (error) { this.logger.error( @@ -170,9 +155,12 @@ export class FileStructureHandler implements BuildHandler { ${removeCodeBlockFences(fileStructureJsonContent)}`, ); + context.virtualDirectory.getAllFiles().forEach((file) => { + this.logger.log(file); + }); return { success: true, - data: removeCodeBlockFences(fileStructureJsonContent), + data: removeCodeBlockFences(fileStructureContent), }; } diff --git a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts index f6fed4ec..449d37c8 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts @@ -22,7 +22,9 @@ export const prompts = { Output Format: Return a JSON object in the following format: +Surround the JSON object with tags. + { "Paths": [ "/full/path/to/file1.ext", @@ -30,11 +32,13 @@ Return a JSON object in the following format: "/another/path/to/file3.ext" ] } + Additional Rules: Maintain the original directory structure but only return files in the JSON output. Keep file names and paths exactly as they appear in the ASCII tree. + Remeber to start with src/ as the root directory (src/...). The root node should correspond to the top-level directory in the tree. Do not include comments or extra fields besides "Paths". Return only the JSON structure (no explanations, no additional comments). This JSON will be used directly in the application. @@ -58,14 +62,15 @@ Additional Rules: roleDescription = 'an expert frontend developer'; includeSections = ` Folder Structure: - components: Reusable UI elements grouped by category (e.g., common, layout, specific). - contexts: Global state management (e.g., auth, theme, player). - hooks: Custom hooks for data fetching and state management. - pages: Route-specific views (e.g., Home, Search, Playlist). - utils: Utility functions (e.g., constants, helpers, validators). - apis: Organized API logic (e.g., auth, music, user). - router.ts: Central routing configuration. - index.tsx: Application entry point. + src: Main source code folder. + components: Reusable UI elements grouped by category (e.g., common, layout, specific). + contexts: Global state management (e.g., auth, theme, player). + hooks: Custom hooks for data fetching and state management. + pages: Route-specific views (e.g., Home, Search, Playlist). + utils: Utility functions (e.g., constants, helpers, validators). + apis: Organized API logic (e.g., auth, music, user). + router.ts: Central routing configuration. + index.tsx: Application entry point. `; excludeSections = ` Do Not Include: diff --git a/backend/src/build-system/utils/file_generator_util.ts b/backend/src/build-system/utils/file_generator_util.ts index e73c007b..920ab07b 100644 --- a/backend/src/build-system/utils/file_generator_util.ts +++ b/backend/src/build-system/utils/file_generator_util.ts @@ -131,12 +131,11 @@ export function buildDependencyGraph(jsonData: { }; details.dependsOn.forEach((dep) => { - const resolvedDep = resolveDependency(fileName, dep); - graph.push([resolvedDep, fileName]); // [dependency, dependent] - nodes.add(resolvedDep); + graph.push([dep, fileName]); // [dependency, dependent] + nodes.add(dep); // store dependsOn - fileInfos[fileName].dependsOn.push(resolvedDep); + fileInfos[fileName].dependsOn.push(dep); }); }); @@ -186,11 +185,6 @@ export function resolveDependency( dependency: string, ): string { const currentDir = path.dirname(currentFile); - const hasExtension = path.extname(dependency).length > 0; - - if (!hasExtension) { - dependency = path.join(dependency, 'index.ts'); - } const resolvedPath = path.join(currentDir, dependency).replace(/\\/g, '/'); logger.log(`Resolved dependency: ${resolvedPath}`); @@ -207,7 +201,7 @@ export function validateAgainstVirtualDirectory( const invalidFiles: string[] = []; nodes.forEach((filePath) => { - if (!virtualDir.isValidFile(filePath)) { + if (!virtualDir.hasFile(filePath)) { invalidFiles.push(filePath); } }); diff --git a/backend/src/build-system/virtual-dir/index.ts b/backend/src/build-system/virtual-dir/index.ts index 71e41bfc..ec64a45a 100644 --- a/backend/src/build-system/virtual-dir/index.ts +++ b/backend/src/build-system/virtual-dir/index.ts @@ -1,140 +1,158 @@ import { Logger } from '@nestjs/common'; -import normalizePath from 'normalize-path'; -import * as path from 'path'; - -interface VirtualNode { - name: string; - isFile: boolean; - children: Map; -} - -interface FileStructureNode { - type: 'file' | 'directory'; - name: string; - children?: FileStructureNode[]; -} export class VirtualDirectory { - private root: VirtualNode; - - constructor() { - this.root = { - name: 'src', - isFile: false, - children: new Map(), - }; - } + private filePaths: Set = new Set(); - private cleanJsonContent(content: string): string { - const jsonStart = content.indexOf('{'); - const jsonEnd = content.lastIndexOf('}'); - return content.slice(jsonStart, jsonEnd + 1); - } + private readonly logger: Logger = new Logger('VirtualDirectory'); public parseJsonStructure(jsonContent: string): boolean { try { const cleanedJson = this.cleanJsonContent(jsonContent); const structure = JSON.parse(cleanedJson); - this.buildTree(structure, this.root); + if (!Array.isArray(structure.Paths)) { + this.logger.error('Invalid JSON format: "Paths" should be an array.'); + return false; + } + + this.filePaths = new Set(structure.Paths); return true; } catch (error) { - Logger.error('Failed to parse JSON structure:', error); + this.logger.error('Failed to parse JSON structure:', error); return false; } } - private buildTree(node: FileStructureNode, virtualNode: VirtualNode): void { - if (node.children) { - for (const child of node.children) { - const newNode: VirtualNode = { - name: child.name, - isFile: child.type === 'file', - children: new Map(), - }; - virtualNode.children.set(child.name, newNode); - - if (child.type === 'directory' && child.children) { - this.buildTree(child, newNode); - } - } - } - } - - public isValidFile(filePath: string): boolean { - const node = this.findNode(filePath); - return node?.isFile ?? false; - } - - isValidDirectory(dirPath: string): boolean { - const node = this.findNode(dirPath); - return node !== null && !node.isFile; - } - - // private findNode(inputPath: string): VirtualNode | null { - // const normalizedPath = this.normalizePath(inputPath); - // const parts = normalizedPath.split('/').filter(Boolean); - - // if (parts[0] !== 'src') { - // return null; - // } - - // let current = this.root; - // for (let i = 1; i < parts.length; i++) { - // const next = current.children.get(parts[i]); - // if (!next) return null; - // current = next; - // } - // return current; - // } - - private findNode(inputPath: string): VirtualNode | null { - const normalizedPath = this.normalizePath(inputPath); - const parts = normalizedPath.split('/').filter(Boolean); - - if (parts.length === 0) { - return null; - } - - // Ensure consistent handling by always requiring 'src' prefix - if (parts[0] !== 'src') { - return null; - } - - parts.shift(); - - let current = this.root; - for (const part of parts) { - const next = current.children.get(part); - if (!next) return null; - current = next; - } - return current; - } - - private normalizePath(inputPath: string): string { - return normalizePath(inputPath); + private cleanJsonContent(jsonContent: string): string { + return jsonContent.trim(); } - resolveRelativePath(fromFile: string, toPath: string): string { - const fromDir = path.dirname(fromFile); - const resolvedPath = path.join(fromDir, toPath).replace(/\\/g, '/'); - return this.normalizePath(resolvedPath); + public hasFile(filePath: string): boolean { + return this.filePaths.has(filePath); } - getAllFiles(): string[] { - const files: string[] = []; - - const traverse = (node: VirtualNode, parentPath: string = '') => { - for (const [name, child] of node.children) { - const currentPath = parentPath ? `${parentPath}/${name}` : name; - if (child.isFile) { - files.push(`src/${currentPath}`); - } - traverse(child, currentPath); - } - }; - - traverse(this.root); - return files.sort(); + public getAllFiles(): string[] { + return Array.from(this.filePaths); } } + +// ---------------------------------- Virtual Directory legacy code for tree stucture---------------------------------- + +// interface VirtualNode { +// name: string; +// isFile: boolean; +// children: Map; +// } + +// interface FileStructureNode { +// type: 'file' | 'directory'; +// name: string; +// children?: FileStructureNode[]; +// } + +// export class VirtualDirectory { +// private root: VirtualNode; + +// constructor() { +// this.root = { +// name: 'src', +// isFile: false, +// children: new Map(), +// }; +// } + +// private cleanJsonContent(content: string): string { +// const jsonStart = content.indexOf('{'); +// const jsonEnd = content.lastIndexOf('}'); +// return content.slice(jsonStart, jsonEnd + 1); +// } + +// public parseJsonStructure(jsonContent: string): boolean { +// try { +// const cleanedJson = this.cleanJsonContent(jsonContent); +// const structure = JSON.parse(cleanedJson); +// this.buildTree(structure, this.root); +// return true; +// } catch (error) { +// Logger.error('Failed to parse JSON structure:', error); +// return false; +// } +// } + +// private buildTree(node: FileStructureNode, virtualNode: VirtualNode): void { +// if (node.children) { +// for (const child of node.children) { +// const newNode: VirtualNode = { +// name: child.name, +// isFile: child.type === 'file', +// children: new Map(), +// }; +// virtualNode.children.set(child.name, newNode); + +// if (child.type === 'directory' && child.children) { +// this.buildTree(child, newNode); +// } +// } +// } +// } + +// public isValidFile(filePath: string): boolean { +// const node = this.findNode(filePath); +// return node?.isFile ?? false; +// } + +// isValidDirectory(dirPath: string): boolean { +// const node = this.findNode(dirPath); +// return node !== null && !node.isFile; +// } + +// private findNode(inputPath: string): VirtualNode | null { +// const normalizedPath = this.normalizePath(inputPath); +// const parts = normalizedPath.split('/').filter(Boolean); + +// if (parts.length === 0) { +// return null; +// } + +// // Ensure consistent handling by always requiring 'src' prefix +// if (parts[0] !== 'src') { +// return null; +// } + +// parts.shift(); + +// let current = this.root; +// for (const part of parts) { +// const next = current.children.get(part); +// if (!next) return null; +// current = next; +// } +// return current; +// } + +// private normalizePath(inputPath: string): string { +// return normalizePath(inputPath); +// } + +// resolveRelativePath(fromFile: string, toPath: string): string { +// const fromDir = path.dirname(fromFile); +// const resolvedPath = path.join(fromDir, toPath).replace(/\\/g, '/'); +// return this.normalizePath(resolvedPath); +// } + +// getAllFiles(): string[] { +// const files: string[] = []; + +// const traverse = (node: VirtualNode, parentPath: string = '') => { +// for (const [name, child] of node.children) { +// const currentPath = parentPath ? `${parentPath}/${name}` : name; +// if (child.isFile) { +// files.push(`src/${currentPath}`); +// } +// traverse(child, currentPath); +// } +// }; + +// traverse(this.root); +// return files.sort(); +// } +// } From 42b06ab0de58df00d0b4539ad7aa8741c93f9b03 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 29 Jan 2025 17:46:58 -0500 Subject: [PATCH 3/5] add line to make sure not forget tag --- .../build-system/handlers/file-manager/file-arch/prompt.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts b/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts index ad8cc233..c19f0c02 100644 --- a/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-arch/prompt.ts @@ -49,5 +49,7 @@ export const generateFileArchPrompt = (): string => { - Include all files in the output, even if they have no dependencies. ### Output -Return only the JSON object wrapped in \`\` tags.`; +Return only the JSON object wrapped in \`\` tags. +Do not forget tags. +`; }; From 3bb38fef536f2fe783c074a616d7b77b0711cb64 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 29 Jan 2025 20:21:08 -0500 Subject: [PATCH 4/5] improve logging and comment --- .../handlers/file-manager/file-arch/index.ts | 55 +++++++++-------- .../file-manager/file-generate/index.ts | 6 +- .../file-manager/file-structure/index.ts | 38 ++++++------ .../build-system/utils/file_generator_util.ts | 61 +++++++++---------- 4 files changed, 84 insertions(+), 76 deletions(-) diff --git a/backend/src/build-system/handlers/file-manager/file-arch/index.ts b/backend/src/build-system/handlers/file-manager/file-arch/index.ts index 15a56afa..ca2ee0b2 100644 --- a/backend/src/build-system/handlers/file-manager/file-arch/index.ts +++ b/backend/src/build-system/handlers/file-manager/file-arch/index.ts @@ -97,36 +97,43 @@ export class FileFAHandler implements BuildHandler { throw new ModelUnavailableError('Model is unavailable:' + error); } - const tagContent = parseGenerateTag(fileArchContent); - const jsonData = extractJsonFromText(tagContent); + try { + const tagContent = parseGenerateTag(fileArchContent); + const jsonData = extractJsonFromText(tagContent); - if (!jsonData) { - this.logger.error('Failed to extract JSON from text'); - throw new ResponseParsingError('Failed to extract JSON from text.'); - } + if (!jsonData) { + this.logger.error('Failed to extract JSON from text'); + throw new ResponseParsingError('Failed to extract JSON from text.'); + } - if (!this.validateJsonData(jsonData)) { - this.logger.error('File architecture JSON validation failed.'); - throw new ResponseParsingError( - 'File architecture JSON validation failed.', - ); - } + if (!this.validateJsonData(jsonData)) { + this.logger.error('File architecture JSON validation failed.'); + throw new ResponseParsingError( + 'File architecture JSON validation failed.', + ); + } - // validate with virutual dir - const { graph, nodes, fileInfos } = buildDependencyGraph(jsonData); + // validate with virutual dir + const { graph, nodes, fileInfos } = buildDependencyGraph(jsonData); - const invalidFiles = validateAgainstVirtualDirectory( - nodes, - this.virtualDir, - ); + const invalidFiles = validateAgainstVirtualDirectory( + nodes, + this.virtualDir, + ); - if (invalidFiles) { - this.logger.error('Validate Against Virtual Directory Fail !!!'); - this.logger.error(`Invalid files detected:\n${invalidFiles}`); - this.logger.error(`${fileArchContent}`); - this.logger.error(`${fileStructure}`); + if (invalidFiles) { + this.logger.error('Validate Against Virtual Directory Fail !!!'); + this.logger.error(`Invalid files detected:\n${invalidFiles}`); + this.logger.error(`${fileArchContent}`); + this.logger.error(`${fileStructure}`); + throw new ResponseParsingError( + 'Failed to validate against virtualDirectory.', + ); + } + } catch (error) { + this.logger.error('File architecture validation failed.'); throw new ResponseParsingError( - 'Failed to validate against virtualDirectory.', + `File architecture JSON validation failed. ${error.message}`, ); } diff --git a/backend/src/build-system/handlers/file-manager/file-generate/index.ts b/backend/src/build-system/handlers/file-manager/file-generate/index.ts index 2c45df49..c8f15989 100644 --- a/backend/src/build-system/handlers/file-manager/file-generate/index.ts +++ b/backend/src/build-system/handlers/file-manager/file-generate/index.ts @@ -138,9 +138,9 @@ export class FileGeneratorHandler implements BuildHandler { const currentDir = path.dirname(currentFile); const hasExtension = path.extname(dependency).length > 0; - if (!hasExtension) { - dependency = path.join(dependency, 'index.ts'); - } + // if (!hasExtension) { + // dependency = path.join(dependency, 'index.ts'); + // } const resolvedPath = path.join(currentDir, dependency).replace(/\\/g, '/'); this.logger.log(`Resolved dependency: ${resolvedPath}`); diff --git a/backend/src/build-system/handlers/file-manager/file-structure/index.ts b/backend/src/build-system/handlers/file-manager/file-structure/index.ts index e36092bc..18721fe3 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/index.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/index.ts @@ -37,7 +37,7 @@ export class FileStructureHandler implements BuildHandler { const sitemapDoc = context.getNodeData(UXSMDHandler); const datamapDoc = context.getNodeData(UXDMDHandler); // const projectPart = opts?.projectPart ?? 'frontend'; - const projectPart = 'frontend'; + const projectPart = opts?.projectPart ?? 'frontend'; const framework = context.getGlobalContext('framework') ?? 'react'; // Validate required arguments @@ -90,6 +90,7 @@ export class FileStructureHandler implements BuildHandler { }, ]; + // Get the generated file structure content let fileStructureContent: string; try { fileStructureContent = await chatSyncWithClocker( @@ -108,11 +109,19 @@ export class FileStructureHandler implements BuildHandler { ); } } catch (error) { - return { success: false, error }; + this.logger.error( + `Failed to generate file structure: ${error.message}`, + error.stack, + ); + return { + success: false, + error: new ResponseParsingError( + `File structure generation failed. ${error.message}`, + ), + }; } - this.logger.log('start parse'); - // Build the virtual directory + // Parse the file structure content let fileStructureJsonContent = ''; try { fileStructureJsonContent = parseGenerateTag(fileStructureContent); @@ -120,12 +129,12 @@ export class FileStructureHandler implements BuildHandler { return { success: false, error: new ResponseParsingError( - 'Failed to parse file Structure Json Content.', + `Failed to parse file Structure Json Content. ${error.message}`, ), }; } - this.logger.log('parse success: ' + fileStructureJsonContent); + // Build the virtual directory this.logger.log('start building'); try { const successBuild = context.buildVirtualDirectory( @@ -136,28 +145,21 @@ export class FileStructureHandler implements BuildHandler { 'Failed to build virtual directory.' + fileStructureJsonContent, ); throw new ResponseParsingError('Failed to build virtual directory.'); - } else { - this.logger.log('build success'); } } catch (error) { - this.logger.error( - 'Non-retryable error during virtual directory build:', - error, - ); return { success: false, - error: new ResponseParsingError('Failed to build virtual directory.'), + error: new ResponseParsingError( + `Failed to build virtual directory. ${error.message}`, + ), }; } - this.logger.log( - `File structure JSON content and virtual directory built successfully. - ${removeCodeBlockFences(fileStructureJsonContent)}`, - ); - + //debug script print all files context.virtualDirectory.getAllFiles().forEach((file) => { this.logger.log(file); }); + return { success: true, data: removeCodeBlockFences(fileStructureContent), diff --git a/backend/src/build-system/utils/file_generator_util.ts b/backend/src/build-system/utils/file_generator_util.ts index 920ab07b..d6d6f1af 100644 --- a/backend/src/build-system/utils/file_generator_util.ts +++ b/backend/src/build-system/utils/file_generator_util.ts @@ -22,6 +22,10 @@ interface GenerateFilesDependencyLayerResult { const logger = new Logger('FileGeneratorUtil'); +/** + * Generate Files Dependency With Layers. + * This function is mainly use for files generate. + */ export async function generateFilesDependencyWithLayers( jsonString: string, virtualDirectory: VirtualDirectory, @@ -38,9 +42,6 @@ export async function generateFilesDependencyWithLayers( // 4. Build concurrency layers with Kahn’s Algorithm const concurrencyLayers = buildConcurrencyLayers(nodes, fileInfos); - // Optionally check for cycles (if you didn’t do it inside buildConcurrencyLayers) - // detectCycles(...) or similar - logger.log('All files dependency layers generated successfully.'); return { @@ -69,40 +70,14 @@ function buildDependencyLayerGraph(jsonData: { // In the JSON, "dependsOn" is an array of file paths details.dependsOn.forEach((dep) => { - const resolvedDep = resolveDependency(fileName, dep); - nodes.add(resolvedDep); - - fileInfos[fileName].dependsOn.push(resolvedDep); + nodes.add(dep); + fileInfos[fileName].dependsOn.push(dep); }); }); return { fileInfos, nodes }; } -/** - * Generates files based on JSON extracted from a Markdown document. - * Ensures dependency order is maintained during file creation. - */ -export async function generateFilesDependency( - markdownContent: string, - virtualDirectory: VirtualDirectory, -): Promise { - const jsonData = extractJsonFromMarkdown(markdownContent); - - const { graph, nodes, fileInfos } = buildDependencyGraph(jsonData); - detectCycles(graph); - validateAgainstVirtualDirectory(nodes, virtualDirectory); - - const sortedFiles = getSortedFiles(graph, nodes); - - logger.log('All files dependency generated successfully.'); - - return { - sortedFiles, - fileInfos, - }; -} - /** * Constructs a dependency graph from the provided JSON structure. * Each file entry includes dependencies that must be resolved first. @@ -142,6 +117,30 @@ export function buildDependencyGraph(jsonData: { return { graph, nodes, fileInfos }; } +/** + * Generates files based on JSON extracted from a Markdown document. + * Ensures dependency order is maintained during file creation. + */ +export async function generateFilesDependency( + markdownContent: string, + virtualDirectory: VirtualDirectory, +): Promise { + const jsonData = extractJsonFromMarkdown(markdownContent); + + const { graph, nodes, fileInfos } = buildDependencyGraph(jsonData); + detectCycles(graph); + validateAgainstVirtualDirectory(nodes, virtualDirectory); + + const sortedFiles = getSortedFiles(graph, nodes); + + logger.log('All files dependency generated successfully.'); + + return { + sortedFiles, + fileInfos, + }; +} + /** * Detects cycles in the dependency graph to prevent infinite loops. */ From 0f079882ff69553730263f7c4f21e51688a9dc68 Mon Sep 17 00:00:00 2001 From: ZHallen122 Date: Wed, 29 Jan 2025 21:08:39 -0500 Subject: [PATCH 5/5] update to avoid page_view folder name --- .../handlers/file-manager/file-structure/prompt.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts index 449d37c8..3bb1ab72 100644 --- a/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts +++ b/backend/src/build-system/handlers/file-manager/file-structure/prompt.ts @@ -80,8 +80,9 @@ Additional Rules: .css files. `; fileNamingGuidelines = ` - File Naming Guidelines: + File and Folder Naming Guidelines: Use meaningful and descriptive file names. + Do NOT use page_view_* and global_view_* prefixes for folder or file names. For components, include an index.tsx file in each folder to simplify imports. Each component should have its own folder named after the component (e.g., Button/). Use index.tsx as the main file inside the component folder.