Skip to content

Commit 28c9814

Browse files
committed
update for using shadcn
1 parent bde7d4c commit 28c9814

File tree

12 files changed

+238
-36
lines changed

12 files changed

+238
-36
lines changed

backend/src/build-system/handlers/file-manager/file-arch/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
buildDependencyGraph,
2323
validateAgainstVirtualDirectory,
2424
} from 'src/build-system/utils/file_generator_util';
25+
import { UXSMSHandler } from '../../ux/sitemap-structure';
2526

2627
@BuildNode()
2728
@BuildNodeRequire([FileStructureHandler, UXDMDHandler])
@@ -36,6 +37,7 @@ export class FileFAHandler implements BuildHandler<string> {
3637

3738
const fileStructure = context.getNodeData(FileStructureHandler);
3839
const datamapDoc = context.getNodeData(UXDMDHandler);
40+
const sitemapStructure = context.getNodeData(UXSMSHandler);
3941

4042
this.logger.log('fileStructure:', fileStructure);
4143
if (!fileStructure || !datamapDoc) {
@@ -57,7 +59,7 @@ export class FileFAHandler implements BuildHandler<string> {
5759
**Page-by-Page Analysis**
5860
The following is a detailed analysis of each page. Use this information to understand specific roles, interactions, and dependencies.
5961
60-
${datamapDoc}
62+
${sitemapStructure}
6163
6264
Next, I will provide the **Directory Structure** to help you understand the full project architecture.`,
6365
},
@@ -77,6 +79,7 @@ export class FileFAHandler implements BuildHandler<string> {
7779
Before returning the output, ensure the following:
7880
- The JSON structure is correctly formatted and wrapped in <GENERATE></GENERATE> tags.
7981
- File extensions and paths match those in the Directory Structure.
82+
- Check if you use ShadCN UI components in "dependsOn" field.
8083
- All files and dependencies are included.`,
8184
},
8285
];
@@ -155,13 +158,22 @@ export class FileFAHandler implements BuildHandler<string> {
155158
}): boolean {
156159
const validPathRegex = /^[a-zA-Z0-9_\-/.]+$/;
157160

161+
const shouldIgnore = (filePath: string) => {
162+
// this.logger.log(`Checking if should ignore: ${filePath}`);
163+
return filePath.startsWith('@/components/ui/');
164+
};
165+
158166
for (const [file, details] of Object.entries(jsonData.files)) {
159167
if (!validPathRegex.test(file)) {
160168
this.logger.error(`Invalid file path: ${file}`);
161169
return false;
162170
}
163171

164172
for (const dependency of details.dependsOn) {
173+
if (shouldIgnore(dependency)) {
174+
continue;
175+
}
176+
165177
if (!validPathRegex.test(dependency)) {
166178
this.logger.error(
167179
`Invalid dependency path "${dependency}" in file "${file}".`,

backend/src/build-system/handlers/file-manager/file-arch/prompt.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,37 @@ export const generateFileArchPrompt = (): string => {
22
return `Your task is to analyze the given project directory structure and create a detailed JSON object mapping file dependencies. The output JSON must be precisely formatted and wrapped in <GENERATE></GENERATE> tags.
33
44
### Instructions
5-
1. **Analyze the Inputs**:
5+
1. Analyze the Inputs:
66
- Use the directory structure to identify all files and folders.
77
- Do not assume any additional files or paths. The structure must be based exclusively on the given list.
88
- Leverage the page-by-page analysis to understand the roles and interactions of different components and pages.
99
- Determine the role of each file based on its path and the provided analysis (e.g., page, component, context, hook, styles).
1010
- Identify direct dependencies for each file by considering typical imports based on roles, naming conventions, and the provided analysis.
1111
12-
2. **Generate File Dependency JSON**:
12+
2. Generate File Dependency JSON:
1313
- Each file must be represented using its full path starting from src/.
1414
- Ensure dependencies are strictly limited to files in the "Paths" array.
15-
- Use absolute file paths from "Paths" for all "dependsOn" values.
16-
Do not use relative paths (./, ../).
17-
Every dependency must match exactly one of the files in "Paths".
18-
- Any file without dependencies should have "dependsOn": [].
19-
- For each file, list its direct dependencies as an array of relative paths in the \`dependsOn\` field.
20-
- Organize the output in a \`files\` object where keys are file paths, and values are their dependency objects.
21-
- For the router, remember to include all the page components as dependencies, as the router imports them to define the application routes.
22-
- For the src/index.tsx, remember to include router.ts.
15+
- Dependencies must only include files explicitly listed in the Paths array.
16+
- Dependencies should be mapped using absolute paths starting from src/. Relative imports (./, ../) must not be used.
17+
- Each file must include a dependsOn field listing only its direct dependencies.
18+
- If a file has no dependencies, set "dependsOn": [].
2319
24-
3. **Output Requirements**:
20+
3. Special Cases:
21+
22+
Router Handling:
23+
The file src/router.ts must include all page components from src/pages/ in its dependsOn field.
24+
Entry Point (src/index.tsx):
25+
Must include src/router.ts as a dependency.
26+
ShadCN UI Components:
27+
Assume all those is in Path the following UI components are available:
28+
["accordion", "alert", "alert-dialog", "aspect-ratio", "avatar", "badge", "breadcrumb", "button", "calendar", "card", "carousel", "chart", "checkbox", "collapsible", "command", "context-menu", "dialog", "drawer", "dropdown-menu", "form", "hover-card", "input", "input-otp", "label", "menubar", "navigation-menu", "pagination", "popover", "progress", "radio-group", "resizable", "scroll-area", "select", "separator", "sheet", "sidebar", "skeleton", "slider", "sonner", "switch", "table", "tabs", "textarea", "toast", "toggle", "toggle-group", "tooltip"]
29+
Any dependencies on these components must be written in the format:
30+
"@/components/ui/{component}.tsx"
31+
Example: If a file depends on "button", it should be:
32+
"dependsOn": ["@/components/ui/button.tsx"]
33+
Ensure all ShadCN UI components are explicitly listed in dependencies.
34+
35+
4. Output Requirements:
2536
- The JSON object must strictly follow this structure:
2637
\`\`\`json
2738
<GENERATE>

backend/src/build-system/handlers/file-manager/file-structure/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { BuilderContext } from 'src/build-system/context';
33
import { prompts } from './prompt';
44
import { Logger } from '@nestjs/common';
55
import {
6+
mergePaths,
67
parseGenerateTag,
78
removeCodeBlockFences,
89
} from 'src/build-system/utils/strings';
@@ -155,14 +156,30 @@ export class FileStructureHandler implements BuildHandler<string> {
155156
};
156157
}
157158

159+
let added_structure = '';
160+
try {
161+
added_structure = mergePaths(fileStructureJsonContent);
162+
if (!added_structure) {
163+
this.logger.error('Failed to add directory.' + added_structure);
164+
throw new ResponseParsingError('Failed to add directory.');
165+
}
166+
} catch (error) {
167+
return {
168+
success: false,
169+
error: new ResponseParsingError(
170+
`Failed to add directory. ${error.message}`,
171+
),
172+
};
173+
}
174+
158175
//debug script print all files
159176
context.virtualDirectory.getAllFiles().forEach((file) => {
160177
this.logger.log(file);
161178
});
162179

163180
return {
164181
success: true,
165-
data: removeCodeBlockFences(fileStructureContent),
182+
data: removeCodeBlockFences(added_structure),
166183
};
167184
}
168185

backend/src/build-system/handlers/file-manager/file-structure/prompt.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ Additional Rules:
130130
- Data Analysis Doc: (provide by user)
131131
132132
### Instructions and Rules:
133-
133+
The final file structure must only have at most 20 files.
134+
134135
Include:
135136
${includeSections}
136137

backend/src/build-system/handlers/frontend-code-generate/CodeReview.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import { readFileSync } from 'fs';
1717
import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper';
1818
import { createFileWithRetries } from 'src/build-system/utils/files';
1919
import { BuilderContext } from 'src/build-system/context';
20-
import { removeCodeBlockFences } from 'src/build-system/utils/strings';
20+
import {
21+
parseGenerateTag,
22+
removeCodeBlockFences,
23+
} from 'src/build-system/utils/strings';
2124
import {
2225
generateCommonErrorPrompt,
2326
generateFileOperationPrompt,
@@ -109,7 +112,7 @@ export class FrontendQueueProcessor {
109112
);
110113

111114
// 1. Write the file to disk
112-
createFileWithRetries(currentFullFilePath, task.fileContents);
115+
await createFileWithRetries(currentFullFilePath, task.fileContents);
113116

114117
const maxFixAttempts = 2;
115118

@@ -207,7 +210,7 @@ export class FrontendQueueProcessor {
207210
let fixResponse = await chatSyncWithClocker(
208211
this.context,
209212
{
210-
model: 'gpt-4o',
213+
model: 'o3-mini-high',
211214
messages: [
212215
{ role: 'system', content: fixPrompt },
213216
{
@@ -239,7 +242,7 @@ export class FrontendQueueProcessor {
239242
},
240243
{
241244
role: 'assistant',
242-
content: `Let me check my result and I must follow the output format.`,
245+
content: `Let me check my result and I must follow the output format I shouldn't write explain outside the json.`,
243246
},
244247
],
245248
},
@@ -250,11 +253,8 @@ export class FrontendQueueProcessor {
250253
this.logger.debug('Fix Response: ' + fixResponse);
251254
this.logger.debug('dependency file Paths ' + task.dependenciesPath);
252255
const parsed_fixResponse = removeCodeBlockFences(fixResponse);
253-
254-
let operations = fileOperationManager.parse(
255-
parsed_fixResponse,
256-
task.filePath,
257-
);
256+
const cleaned_Data = parseGenerateTag(parsed_fixResponse);
257+
let operations = fileOperationManager.parse(cleaned_Data, task.filePath);
258258

259259
// **If LLM requested additional files, read them**
260260
if (operations.some((op) => op.action === 'read')) {
@@ -319,7 +319,7 @@ export class FrontendQueueProcessor {
319319
},
320320
{
321321
role: 'assistant',
322-
content: `Let me check my result and I must follow the output format`,
322+
content: `Let me check my result and I must follow the output format I shouldn't write explain outside the json`,
323323
},
324324
],
325325
},

backend/src/build-system/handlers/frontend-code-generate/index.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ export class FrontendCodeHandler implements BuildHandler<string> {
8282
const { concurrencyLayers, fileInfos } =
8383
await generateFilesDependencyWithLayers(fileArchDoc, this.virtualDir);
8484

85+
// concurrencyLayers.forEach((layer, index) => {
86+
// console.log(`Layer #${index + 1} has ${layer.length} file(s):`, layer);
87+
// });
88+
89+
// Object.entries(fileInfos).forEach(([filePath, info]) => {
90+
// this.logger.debug(`File: ${filePath}`);
91+
// this.logger.debug(`Depends On: ${info.dependsOn.join(', ')}`);
92+
// });
93+
8594
const validator = new FrontendCodeValidator(frontendPath);
8695
// validator.installDependencies();
8796

@@ -224,7 +233,19 @@ export class FrontendCodeHandler implements BuildHandler<string> {
224233

225234
for (const dep of directDepsArray) {
226235
try {
227-
const resolvedDepPath = normalizePath(path.resolve(frontendPath, dep));
236+
let resolvedDepPath = dep;
237+
238+
// Resolve alias-based paths (assuming `@/` maps to `frontendPath/src/`)
239+
if (dep.startsWith('@/')) {
240+
resolvedDepPath = path.join(
241+
frontendPath,
242+
'src',
243+
dep.replace(/^@\//, ''),
244+
);
245+
} else {
246+
resolvedDepPath = normalizePath(path.resolve(frontendPath, dep));
247+
}
248+
228249
const depContent = await readFileWithRetries(resolvedDepPath, 3, 200);
229250
dependenciesText += `\n\n<dependency> File path: ${dep}\n\`\`\`typescript\n${depContent}\n\`\`\`\n</dependency>`;
230251
} catch (err) {
@@ -324,7 +345,7 @@ export class FrontendCodeHandler implements BuildHandler<string> {
324345
modelResponse = await chatSyncWithClocker(
325346
context,
326347
{
327-
model: 'gpt-4o',
348+
model: 'gpt-4o-mini',
328349
messages,
329350
},
330351
'generate frontend code',

backend/src/build-system/handlers/frontend-code-generate/prompt.ts

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,21 @@ export const generateFrontEndCodePrompt = (
1313
4. Follow design: DONT CHANGE ANY DESIGN IN Document.
1414
5. CAREFULLY CHECK:
1515
Before importing a file, verify its existence.
16-
THAT YOU DONT MISSED ANY Internal Dependencies import.
17-
If missing, suggest an alternative or define mock data.
1816
6. Before using a external variable/module, make sure you import it first.
1917
7. Error Handling: Implement proper error handling in API calls and interactions with external modules.
20-
8. Code Standards: Adhere to styling guidelines (e.g., Tailwind CSS, CSS Modules), and Use only Tailwind UI for styling, applying all styles via inline class names (className).
21-
9. Mock the response: if the API returns an empty or undefined value.
22-
10. Write EVERY CODE DETAIL, DON'T LEAVE TODO.
18+
8. Code Standards: Must build good Css. Must use Tailwind UI for styling, applying all styles via inline class names (className).
19+
9. Mock Data (Where Applicable):
20+
- If the component or page needs to display a list of items, create a small realistic example.
21+
- Provide enough mock data to display the UI meaningfully .
22+
- If no data is present (empty array), show a simple fallback (e.g. No data found.).
23+
10. Mock the response: if the API returns an empty or undefined value.
24+
11. Write EVERY CODE DETAIL, DON'T LEAVE TODO.
2325
2426
## Library:
2527
"react-router": "^6",
2628
"react": "^18",
2729
"@tailwindcss/vite": "^4.0.0"
2830
29-
3031
## Output Format:
3132
Output your final code wrapped in <GENERATE> tags ONLY, like:
3233
@@ -36,6 +37,51 @@ export const generateFrontEndCodePrompt = (
3637
`;
3738
};
3839

40+
// export const generateFrontEndCodePrompt = (
41+
// currentFile: string,
42+
// dependencyFilePath: string,
43+
// ): string => {
44+
// return `Role: You are an expert frontend developer specializing in building scalable, maintainable, and production-ready React applications using TypeScript.
45+
// Task: Generate complete, type-safe, and maintainable React code.
46+
// Current File: ${currentFile}.
47+
48+
// # Instructions and Rules:
49+
// 1. Implement Only One file: Implement only the given file.
50+
// 2. COMPLETE CODE: Your code will be part of the entire project, so please implement complete, reliable, reusable code snippets.
51+
// 3. Type Safe: Follow typscript standard.
52+
// 4. Follow design: DONT CHANGE ANY DESIGN IN Document.
53+
// 5. CAREFULLY CHECK:
54+
// Before importing a file, verify its existence.
55+
// THAT YOU DONT MISSED ANY Internal Dependencies import.
56+
// If missing, suggest an alternative or define mock data.
57+
// 6. Before using a external variable/module, make sure you import it first.
58+
// 7. Error Handling: Implement proper error handling in API calls and interactions with external modules.
59+
// 8. Code and Styling Standards:
60+
// Use Shadcn UI components ONLY.
61+
// Use '@/components/ui/*' for Shadcn.
62+
// ONLY use @/components/ui/* for Shadcn UI components Do Not Use things like @/api.
63+
// DO NOT use \`@tanstack/react-query\`, \`use-debounce\`, \`react-toastify\`
64+
// 9. Mock the response: if the API returns an empty or undefined value.
65+
// 10. Write EVERY CODE DETAIL, DON'T LEAVE TODO.
66+
67+
// ## Library:
68+
// "react-router": "^6",
69+
// "react": "^18",
70+
// @radix-ui/react-select": "^2",
71+
// ........
72+
73+
// ## Shadcn UI Components:
74+
// accordion, alert, alert-dialog, aspect-ratio, avatar, badge, breadcrumb, button, calendar, card, carousel, chart, checkbox, collapsible, command, context-menu, dialog, drawer, dropdown-menu, form, hover-card, input, input-otp, label, menubar, navigation-menu, pagination, popover, progress, radio-group, resizable, scroll-area, select, separator, sheet, sidebar, skeleton, slider, sonner, switch, table, tabs, textarea, toast, toggle, toggle-group, tooltip
75+
76+
// ## Output Format:
77+
// Output your final code wrapped in <GENERATE> tags ONLY, like:
78+
79+
// <GENERATE>
80+
// ...full code...
81+
// </GENERATE>
82+
// `;
83+
// };
84+
3985
export function generateCSSPrompt(
4086
fileName: string,
4187
directDependencies: string,
@@ -159,6 +205,7 @@ Available operations:
159205
Not assignable to parameter of type → Use the READ tool if you dont have enough information to fix.
160206
161207
**Output format:**
208+
Return only the JSON object wrapped in \`<GENERATE></GENERATE>\` tags.
162209
To keep the structure consistent, other operations remain single-action:
163210
164211
1. Read File
@@ -194,6 +241,8 @@ If a file needs to be renamed:
194241
}
195242
}
196243
}
244+
245+
Do not forget <GENERATE></GENERATE> tags.
197246
`;
198247
}
199248

backend/src/build-system/utils/file_generator_util.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,16 @@ function buildDependencyLayerGraph(jsonData: {
6060
const fileInfos: Record<string, FileDependencyInfo> = {};
6161
const nodes = new Set<string>();
6262

63+
const shouldIgnore = (filePath: string) => {
64+
// this.logger.log(`Checking if should ignore: ${filePath}`);
65+
return filePath.startsWith('@/components/ui/');
66+
};
67+
6368
Object.entries(jsonData.files).forEach(([fileName, details]) => {
69+
if (shouldIgnore(fileName)) {
70+
return;
71+
}
72+
6473
nodes.add(fileName);
6574

6675
// Initialize the record
@@ -69,8 +78,16 @@ function buildDependencyLayerGraph(jsonData: {
6978
dependsOn: [],
7079
};
7180

81+
const filteredDeps = (details.dependsOn || []).filter(
82+
(dep) => !shouldIgnore(dep),
83+
);
84+
7285
// In the JSON, "dependsOn" is an array of file paths
73-
details.dependsOn.forEach((dep) => {
86+
// details.dependsOn.forEach((dep) => {
87+
// nodes.add(dep);
88+
// fileInfos[fileName].dependsOn.push(dep);
89+
// });
90+
filteredDeps.forEach((dep) => {
7491
nodes.add(dep);
7592
fileInfos[fileName].dependsOn.push(dep);
7693
});

0 commit comments

Comments
 (0)