Skip to content

refactor(backend): optimization build system prompt, support more features #133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Mar 16, 2025
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e5f384c
remove
ZHallen122 Feb 17, 2025
1a23c41
update safe check
ZHallen122 Feb 18, 2025
bde7d4c
Update template
ZHallen122 Feb 21, 2025
28c9814
update for using shadcn
ZHallen122 Feb 22, 2025
7c318a8
feat(frontend): Code Engine preview, support preview project right no…
NarwhalChen Feb 19, 2025
8860ae1
chore: little fixing in code engine (#126)
Sma1lboy Feb 19, 2025
e0f6903
feat(monitor): enhance execution monitoring with detailed node metric…
Sma1lboy Feb 19, 2025
090797d
Merge remote-tracking branch 'origin/main' into feat-React-CSS-Compon…
ZHallen122 Feb 26, 2025
45ad0e1
[autofix.ci] apply automated fixes
autofix-ci[bot] Feb 26, 2025
5b993f2
update prompt for shadcn, reponse design and merge list
ZHallen122 Feb 27, 2025
aa094e6
dont tell a exmaple may get a better result
ZHallen122 Feb 27, 2025
23171a3
Merge branch 'main' into feat-React-CSS-Components-Lib
Sma1lboy Mar 2, 2025
7db47da
feat(backend): update project description and enhance global componen…
Sma1lboy Mar 2, 2025
d75d50e
feat(frontend): enhance prompt guidelines with detailed design and or…
Sma1lboy Mar 9, 2025
eb9cbd8
fix file arch reference ui incorrect
ZHallen122 Mar 11, 2025
6a97fe1
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 11, 2025
9cffc85
UIUX handler
ZHallen122 Mar 12, 2025
190512f
Add product requirement
ZHallen122 Mar 13, 2025
71ab5cd
Merge branch 'feat-React-CSS-Components-Lib' of https://github.com/Sm…
ZHallen122 Mar 13, 2025
1ae1703
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 13, 2025
53795a2
update import
ZHallen122 Mar 13, 2025
1e0ffc9
Merge branch 'feat-React-CSS-Components-Lib' of https://github.com/Sm…
ZHallen122 Mar 13, 2025
38e34d6
test
ZHallen122 Mar 13, 2025
117ace2
update
ZHallen122 Mar 13, 2025
02177d0
update
ZHallen122 Mar 14, 2025
9ed1ea7
improve prompt
ZHallen122 Mar 15, 2025
d8fc801
update
ZHallen122 Mar 15, 2025
0dc830f
update prompts
ZHallen122 Mar 15, 2025
99c5fb5
add package
ZHallen122 Mar 15, 2025
97f8771
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 15, 2025
2f1ac00
UIUX with calude
ZHallen122 Mar 15, 2025
c1679a8
[autofix.ci] apply automated fixes
autofix-ci[bot] Mar 15, 2025
29e3814
update frontend
ZHallen122 Mar 15, 2025
864d888
Merge branch 'feat-React-CSS-Components-Lib' of https://github.com/Sm…
ZHallen122 Mar 15, 2025
9011e07
remove layout
ZHallen122 Mar 15, 2025
f28ae56
add color pattern
ZHallen122 Mar 15, 2025
2be75ad
improve escape situation
ZHallen122 Mar 16, 2025
5dc8957
remove wirefram drawing
ZHallen122 Mar 16, 2025
3581cc3
Merge remote-tracking branch 'origin/main' into feat-React-CSS-Compon…
ZHallen122 Mar 16, 2025
41e03e9
comment the old test
ZHallen122 Mar 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions backend/src/build-system/__tests__/fullstack-gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import { BuilderContext } from '../context';
import { FrontendCodeHandler } from '../handlers/frontend-code-generate';
import { FileStructureAndArchitectureHandler } from '../handlers/file-manager/file-struct';
import { BackendRequirementHandler } from '../handlers/backend/requirements-document';
import { UIUXLayoutHandler } from '../handlers/ux/uiux-layout';

(isIntegrationTest ? describe : describe.skip)('Build Sequence Test', () => {
it('should execute build sequence successfully', async () => {
const sequence: BuildSequence = {
id: 'test-backend-sequence',
version: '1.0.0',
name: 'Wrtie a Cool personal website',
description:
'A personal blog website. I am a cybersecurity engineer so i want it to show i am a really cool hacker, with cool terminal functionality',
name: 'Wrtie a Single page Cool cybersecurity personal website',
description: `A Single page personal blog website. I am a cybersecurity engineer so i want it to show i am a really cool hacker, with cool terminal functionality`,
databaseType: 'SQLite',
model: 'gpt-4o-mini',
projectSize: 'medium', // limit for fun
Expand All @@ -40,6 +40,11 @@ import { BackendRequirementHandler } from '../handlers/backend/requirements-docu
name: 'UX Sitemap Structure Node',
// requires: ['op:UX:SMD'],
},
{
handler: UIUXLayoutHandler,
name: 'UIUX Layout Handler',
// requires: ['op:UX:SMD'],
},
{
handler: UXDMDHandler,
name: 'UX DataMap Document Node',
Expand Down
128 changes: 112 additions & 16 deletions backend/src/build-system/handlers/file-manager/file-struct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
removeCodeBlockFences,
extractJsonFromText,
formatResponse,
mergePaths,
} from 'src/build-system/utils/strings';
import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper';
import {
Expand Down Expand Up @@ -33,7 +34,7 @@ export const prompts = {

Output Format:
Return a JSON object in the following format:
Surround the JSON object with <GENERATE> tags.
You must surround the JSON object with <GENERATE> tags.

<GENERATE>
{
Expand Down Expand Up @@ -109,7 +110,7 @@ export const prompts = {
switch (projectPart.toLowerCase()) {
case 'frontend':
roleDescription = 'an expert frontend developer';
includeSections = `
includeSections = `
Non-SPA Folder Structure example:
src/
contexts/ - Global state management
Expand All @@ -121,8 +122,10 @@ export const prompts = {
? `SPA Folder Structure (MANDATORY for all SPAs):
src/
index.tsx - Main entry point that imports Home page
layout.tsx - Global Layout
pages/
Home/

index.tsx - Contains ALL component code and application logic

For SPAs, you MUST use exactly this structure - no variations allowed.`
Expand All @@ -146,7 +149,7 @@ export const prompts = {
${
isSPAFlag
? `For SPAs:
- Only create the exact files specified: src/index.tsx and src/pages/Home/index.tsx
- Only create the exact files specified: src/index.tsx, layout.tsx and src/pages/Home/index.tsx
- Do not create any additional files or folders`
: ''
}
Expand Down Expand Up @@ -236,30 +239,37 @@ Output Format:

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.

### Instructions
# Instructions

${
isSPAFlag
? `**SPA Special Case**:
- If the structure only contains src/index.tsx and src/pages/Home/index.tsx, this is a Single Page Application (SPA) with the mandatory minimal structure.
- If the structure only contains src/index.tsx and src/pages/Home/index.tsx, src/layout.tsx this is a Single Page Application (SPA) with the mandatory minimal structure.
- For SPAs with this exact structure, the JSON must look like this:
\`\`\`json
<GENERATE>
{
"files": {
"src/index.tsx": {
"dependsOn": ["src/pages/Home/index.tsx"]
"dependsOn": ["src/pages/Home/index.tsx", "src/layout.tsx"]
},
"src/pages/Home/index.tsx": {
"dependsOn": []
}
},
"src/layout.tsx": {
"dependsOn": []
},
}
}
</GENERATE>
\`\`\`

- IMPORTANT EXCEPTION FOR UI COMPONENTS:
- Even in SPA mode, shadcn UI component dependencies ARE ALLOWED and SHOULD be added
- For the Home page, add appropriate shadcn UI dependencies from the available file structure
- This is MANDATORY: for SPAs, create exactly these two files with exactly these dependencies - no more, no less.

**For non-SPA projects**: `
## For non-SPA projects: `
: 'For projects'
}
- Analyze the directory structure to identify all files and folders.
Expand All @@ -269,7 +279,7 @@ Output Format:
- Identify direct dependencies for each file by considering typical imports based on roles, naming conventions, and the provided analysis.
- For context files, ensure they are properly referenced in index.tsx or router.tsx, as contexts typically need to be provided at a high level in the application.

3. **Generate File Dependency JSON**:
## 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.
Expand All @@ -280,16 +290,54 @@ Output Format:
- 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.

4. **Output Requirements**:
## UI Component Dependencies:
- This project uses the shadcn UI component library.
- Components that likely need UI elements (forms, buttons, inputs, etc.) should include appropriate shadcn component dependencies.
- Shadcn components are imported with the syntax @/components/ui/[component-name].tsx
- Analyze component purposes carefully to determine which shadcn components they should depend on
- Examples:
- A data table component should depend on table.tsx
- A navigation component with dropdowns should depend on dropdown-menu.tsx

## Balanced Dependency Approach:
- Most components should have 1-3 relevant UI dependencies
- Complex components (like forms or tables) may have more
- Simple components may have just one or even none

## Global Components Usage:
- Consider how global components are used across pages.
- Global components (like navigation bars, footers, layouts) should be dependencies for all page components.
- For example, a Nav component should be included as a dependency for all page files.
- Ensure these global components are properly represented in the dependency tree for all relevant pages.

## CRITICAL: STRICT DEPENDENCY VALIDATION

1. Allowlist-Only Approach:
- Create an internal allowlist containing ONLY the exact file paths from the provided file structure
- EVERY dependency MUST EXACTLY match one of the paths in this allowlist
- NO EXCEPTIONS: If a logical UI component doesn't exist in the allowlist, DO NOT ADD IT

2. Verification Process:
- After generating each file's dependencies, VERIFY each dependency against the allowlist
- If any dependency is not in the allowlist, REMOVE it immediately
- For UI components, ONLY use paths that are EXACTLY as listed in the file structure

3. **Before Generating Output**:
- Perform a final validation pass to ensure EVERY dependency exists in the allowlist
- Remove ANY dependencies that don't have an exact match in the file structure

This is mission-critical: The system will reject ANY file references that don't exactly match the provided structure.

## Output Requirements:
- The JSON object must strictly follow this structure:
\`\`\`json
<GENERATE>
{
"files": {
"src/path/to/file1": {
"src/index.tsx": {
"dependsOn": ["src/path/to/dependency1", "src/path/to/dependency2"]
},
"src/path/to/file2": {
"src/path/to/file1": {
"dependsOn": []
}
}
Expand All @@ -301,14 +349,19 @@ Output Format:
All dependencies must exist in the "Paths" array.
No inferred or assumed files should be added.
- Wrap the JSON output with \`<GENERATE></GENERATE>\` tags.
### Notes

## Notes
- 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.
- For context providers, ensure they are included as dependencies in either index.tsx or router.tsx to maintain proper context hierarchy in the React application.
- Global components like navigation bars should appear as dependencies in all page components.
- Include all files in the output, even if they have no dependencies.

### Output
## Validation Step
Before finalizing, verify each UI component dependency against the complete list of available UI components. Remove any dependency that doesn't have an exact match in the file structure.

## Output
Return only the JSON object wrapped in \`<GENERATE></GENERATE>\` tags.
Do not forget <GENERATE></GENERATE> tags.
`;
Expand Down Expand Up @@ -349,6 +402,14 @@ export class FileStructureAndArchitectureHandler
};
}

// Calculate isSPA flag based on sitemap
const pageViewCount = (sitemapDoc.match(/page_view_/g) || []).length;
const isSPAFlag = pageViewCount === 1;

this.logger.log(`Is SPA: ${isSPAFlag}`);

context.setGlobalContext('isSPAFlag', isSPAFlag);

const fileStructPrompt = prompts.generateCommonFileStructurePrompt(
projectName,
sitemapDoc,
Expand Down Expand Up @@ -457,6 +518,22 @@ export class FileStructureAndArchitectureHandler
};
}

let added_structure = '';
try {
added_structure = mergePaths(fileStructureJsonContent);
if (!added_structure) {
this.logger.error('Failed to add directory.' + added_structure);
throw new ResponseParsingError('Failed to add directory.');
}
} catch (error) {
return {
success: false,
error: new ResponseParsingError(
`Failed to add directory. ${error.message}`,
),
};
}

context.virtualDirectory.getAllFiles().forEach((file) => {
this.logger.log(file);
});
Expand All @@ -466,7 +543,7 @@ export class FileStructureAndArchitectureHandler
this.logger.log('Generating File Architecture Document...');

this.virtualDir = context.virtualDirectory;
const fileStructure = removeCodeBlockFences(fileStructureContent);
const fileStructure = removeCodeBlockFences(added_structure);
if (!fileStructure || !datamapDoc) {
return {
success: false,
Expand Down Expand Up @@ -552,12 +629,17 @@ export class FileStructureAndArchitectureHandler
}

if (!this.validateJsonData(jsonData)) {
this.logger.error('File architecture JSON validation failed.');
this.logger.error(
'File architecture JSON validation failed.',
fileArchContent,
);
throw new ResponseParsingError(
'File architecture JSON validation failed.',
);
}

this.logger.debug(fileArchContent);

const { nodes } = buildDependencyGraph(jsonData);
invalidFiles = validateAgainstVirtualDirectory(nodes, this.virtualDir);
if (invalidFiles) {
Expand Down Expand Up @@ -598,18 +680,32 @@ export class FileStructureAndArchitectureHandler
}
}

/**
* Validates the structure and content of the JSON data.
* @param jsonData The JSON data to validate.
* @returns A boolean indicating whether the JSON data is valid.
*/
private validateJsonData(jsonData: {
files: Record<string, { dependsOn: string[] }>;
}): boolean {
const validPathRegex = /^[a-zA-Z0-9_\-/.]+$/;

const shouldIgnore = (filePath: string) => {
// this.logger.log(`Checking if should ignore: ${filePath}`);
return filePath.startsWith('@/components/ui/');
};

for (const [file, details] of Object.entries(jsonData.files)) {
if (!validPathRegex.test(file)) {
this.logger.error(`Invalid file path: ${file}`);
return false;
}

for (const dependency of details.dependsOn) {
if (shouldIgnore(dependency)) {
continue;
}

if (!validPathRegex.test(dependency)) {
this.logger.error(
`Invalid dependency path "${dependency}" in file "${file}".`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { readFileSync } from 'fs';
import { chatSyncWithClocker } from 'src/build-system/utils/handler-helper';
import { createFileWithRetries } from 'src/build-system/utils/files';
import { BuilderContext } from 'src/build-system/context';
import { removeCodeBlockFences } from 'src/build-system/utils/strings';
import {
parseGenerateTag,
removeCodeBlockFences,
} from 'src/build-system/utils/strings';
import {
generateCommonErrorPrompt,
generateFileOperationPrompt,
Expand Down Expand Up @@ -227,7 +230,7 @@ export class FrontendQueueProcessor {
},
{
role: 'assistant',
content: `Let me check my result and I must follow the output format.`,
content: `Let me check my result and I must follow the output format I shouldn't write explain outside the json.`,
},
],
},
Expand All @@ -238,11 +241,8 @@ export class FrontendQueueProcessor {
this.logger.debug('Fix Response: ' + fixResponse);
this.logger.debug('dependency file Paths ' + task.dependenciesPath);
const parsed_fixResponse = removeCodeBlockFences(fixResponse);

let operations = fileOperationManager.parse(
parsed_fixResponse,
task.filePath,
);
const cleaned_Data = parseGenerateTag(parsed_fixResponse);
let operations = fileOperationManager.parse(cleaned_Data, task.filePath);

// **If LLM requested additional files, read them**
if (operations.some((op) => op.action === 'read')) {
Expand Down Expand Up @@ -307,7 +307,7 @@ export class FrontendQueueProcessor {
},
{
role: 'assistant',
content: `Let me check my result and I must follow the output format`,
content: `Let me check my result and I must follow the output format I shouldn't write explain outside the json`,
},
],
},
Expand Down
Loading
Loading