Skip to content

Commit bf20035

Browse files
committed
refactor: improve error handling, prompt clarity, and template filtering
Add null checks after inference calls in blueprint, template selection, phase generation, user conversation processing, project setup, and code fixer operations. Switch from REACT_RENDER_LOOP_PREVENTION to REACT_RENDER_LOOP_PREVENTION_LITE in code debugger and phase generation. Add explicit warning against installing cloudflare:workers/durable-objects dependencies in multiple prompts. Update phase generation to prioritize runtime
1 parent 9f9cc7a commit bf20035

File tree

11 files changed

+86
-44
lines changed

11 files changed

+86
-44
lines changed

worker/agents/assistants/codeDebugger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ The goal is working code, verified through evidence. Think internally, act decis
459459
<appendix>
460460
The most important class of errors is the "Maximum update depth exceeded" error which you definitely need to identify and fix.
461461
Here are some important guidelines for identifying such issues and preventing them:
462-
${PROMPT_UTILS.REACT_RENDER_LOOP_PREVENTION}
462+
${PROMPT_UTILS.REACT_RENDER_LOOP_PREVENTION_LITE}
463463
464464
${PROMPT_UTILS.COMMON_DEP_DOCUMENTATION}
465465

worker/agents/assistants/projectsetup.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ Output:
6060
- Focus on blueprint requirements only
6161
- cloudflare:workers is not needed, it's already installed
6262
63+
**Do not recommend installing \`cloudflare:workers\` or \`cloudflare:durable-objects\` as dependencies, these are already installed in the project always.**
64+
6365
${PROMPT_UTILS.COMMANDS}
6466
6567
<INPUT DATA>
@@ -128,6 +130,12 @@ ${error}`);
128130
context: this.inferenceContext,
129131
modelName: error? AIModels.GEMINI_2_5_FLASH : undefined,
130132
});
133+
134+
if (!results || !results.string) {
135+
this.logger.error('Project setup returned no result after all retries');
136+
throw new Error('Failed to generate setup commands: inference returned null');
137+
}
138+
131139
this.logger.info(`Generated setup commands: ${results.string}`);
132140

133141
this.save([createAssistantMessage(results.string)]);

worker/agents/core/simpleGeneratorAgent.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { ScreenshotAnalysisOperation } from '../operations/ScreenshotAnalysis';
3030
// Database schema imports removed - using zero-storage OAuth flow
3131
import { BaseSandboxService } from '../../services/sandbox/BaseSandboxService';
3232
import { WebSocketMessageData, WebSocketMessageType } from '../../api/websocketTypes';
33-
import { InferenceContext, ModelConfig } from '../inferutils/config.types';
33+
import { InferenceContext } from '../inferutils/config.types';
3434
import { ModelConfigService } from '../../database/services/ModelConfigService';
3535
import { fixProjectIssues } from '../../services/code-fixer';
3636
import { GitVersionControl } from '../git';
@@ -355,22 +355,14 @@ export class SimpleCodeGeneratorAgent extends Agent<Env, CodeGenState> {
355355
// Load the latest user configs
356356
const modelConfigService = new ModelConfigService(this.env);
357357
const userConfigsRecord = await modelConfigService.getUserModelConfigs(this.state.inferenceContext.userId);
358-
359-
const userModelConfigs: Record<string, ModelConfig> = {};
360-
for (const [actionKey, mergedConfig] of Object.entries(userConfigsRecord)) {
361-
if (mergedConfig.isUserOverride) {
362-
const { isUserOverride, userConfigId, ...modelConfig } = mergedConfig;
363-
userModelConfigs[actionKey] = modelConfig;
364-
}
365-
}
366358
this.setState({
367359
...this.state,
368360
inferenceContext: {
369361
...this.state.inferenceContext,
370-
userModelConfigs,
362+
userModelConfigs: userConfigsRecord,
371363
},
372364
});
373-
this.logger().info(`Agent ${this.getAgentId()} session: ${this.state.sessionId} onStart: User configs loaded successfully`, {userModelConfigs});
365+
this.logger().info(`Agent ${this.getAgentId()} session: ${this.state.sessionId} onStart: User configs loaded successfully`, {userConfigsRecord});
374366
}
375367

376368
private async gitInit() {
@@ -1702,6 +1694,8 @@ export class SimpleCodeGeneratorAgent extends Agent<Env, CodeGenState> {
17021694
}
17031695

17041696
const regenerated = await this.regenerateFile({ filePath: path, fileContents, filePurpose }, issues, 0);
1697+
// Invalidate cache
1698+
this.staticAnalysisCache = null;
17051699
// Persist to sandbox instance
17061700
await this.getSandboxServiceClient().writeFiles(sandboxInstanceId, [{ filePath: regenerated.filePath, fileContents: regenerated.fileContents }], `Deep debugger fix: ${path}`);
17071701
return { path, diff: regenerated.lastDiff };
@@ -1766,6 +1760,8 @@ export class SimpleCodeGeneratorAgent extends Agent<Env, CodeGenState> {
17661760
fileCount: result.files.length
17671761
});
17681762

1763+
await this.deployToSandbox(savedFiles, false);
1764+
17691765
return { files: savedFiles.map(f => {
17701766
return {
17711767
path: f.filePath,

worker/agents/operations/PhaseGeneration.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const SYSTEM_PROMPT = `<ROLE>
2424
<TASK>
2525
You are given the blueprint (PRD) and the client query. You will be provided with all previously implemented project phases, the current latest snapshot of the codebase, and any current runtime issues or static analysis reports.
2626
27-
**Your primary task:** Design the next phase of the project as a deployable milestone leading to project completion or to address any user feedbacks or reported bugs.
27+
**Your primary task:** Design the next phase of the project as a deployable milestone leading to project completion or to address any user feedbacks or reported bugs (runtime error fixing is the highest priority).
2828
2929
**Phase Planning Process:**
3030
1. **ANALYZE** current codebase state and identify what's implemented vs. what remains
@@ -36,6 +36,8 @@ const SYSTEM_PROMPT = `<ROLE>
3636
- **Accessibility**: Proper semantic HTML, ARIA labels, keyboard navigation
3737
- **Supreme software development practices**: Follow the best coding principles and practices, and lay out the codebase in a way that is easy to maintain, extend and debug.
3838
4. **VALIDATE** that the phase will be deployable with all views/pages working beautifully across devices
39+
40+
Plan the phase name and description appropriately. They don't have to strictly adhere to the blueprint's roadmap as unforeseen issues may occur.
3941
4042
The project needs to be fully ready to ship in a reasonable amount of time. Plan accordingly.
4143
If no more phases are needed, conclude by putting blank fields in the response.
@@ -230,7 +232,7 @@ const issuesPromptFormatterWithGuidelines = (issues: IssueReport): string => {
230232
serialized = `
231233
${PROMPT_UTILS.COMMON_PITFALLS}
232234
233-
${issues.runtimeErrors.some((error) => error.message.includes('infinite loop') || error.message.includes('re-renders')) ? PROMPT_UTILS.REACT_RENDER_LOOP_PREVENTION: ''}
235+
${issues.runtimeErrors.some((error) => error.message.includes('infinite loop') || error.message.includes('re-renders')) ? PROMPT_UTILS.REACT_RENDER_LOOP_PREVENTION_LITE: ''}
234236
235237
${serialized}`;
236238
}
@@ -293,6 +295,11 @@ export class PhaseGenerationOperation extends AgentOperation<PhaseGenerationInpu
293295
format: 'markdown',
294296
});
295297

298+
if (!results) {
299+
logger.error('Phase generation returned no result after all retries');
300+
throw new Error('Failed to generate next phase: inference returned null');
301+
}
302+
296303
logger.info(`Generated next phase: ${results.name}, ${results.description}`);
297304

298305
return results;

worker/agents/operations/PostPhaseCodeFixer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ export class FastCodeFixerOperation extends AgentOperation<FastCodeFixerInputs,
9797
context: options.inferenceContext,
9898
});
9999

100+
if (!result || !result.string) {
101+
logger.error('Fast code fixer returned no result after all retries');
102+
throw new Error('Failed to fix code issues: inference returned null');
103+
}
104+
100105
const files = codeGenerationFormat.deserialize(result.string);
101106
return files;
102107
}

worker/agents/operations/UserConversationProcessor.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,11 @@ export class UserConversationProcessor extends AgentOperation<UserConversationIn
430430
}
431431
}
432432

433+
if (!result || !result.string) {
434+
logger.error('User message processing returned no result');
435+
throw new Error('Failed to process user message: inference returned null');
436+
}
437+
433438
logger.info("Successfully processed user message", {
434439
streamingSuccess: !!extractedUserResponse,
435440
});
@@ -663,6 +668,11 @@ Provide the summary now:`
663668
context: options.inferenceContext,
664669
});
665670

671+
if (!summaryResult || !summaryResult.string) {
672+
logger.error('Conversation summarization returned no result');
673+
throw new Error('Failed to generate conversation summary: inference returned null');
674+
}
675+
666676
const summary = summaryResult.string.trim();
667677

668678
logger.info('Generated conversation summary', {

worker/agents/planning/blueprint.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const logger = createLogger('Blueprint');
1515

1616
const SYSTEM_PROMPT = `<ROLE>
1717
You are a meticulous and forward-thinking Senior Software Architect and Product Manager at Cloudflare with extensive expertise in modern UI/UX design and visual excellence.
18-
Your expertise lies in designing clear, concise, comprehensive, and unambiguous blueprints (PRDs) for building production-ready scalable and visually stunning, piece-of-art web applications that users will love to use.
18+
Your expertise lies in designing clear, concise, comprehensive, and unambiguous blueprints (PRDs) for building production-ready scalable and visually stunning, piece-of-art web applications that users will love to use, using Cloudflare workers and durable objects.
1919
</ROLE>
2020
2121
<TASK>
@@ -24,7 +24,8 @@ const SYSTEM_PROMPT = `<ROLE>
2424
Focus on a clear and comprehensive design that prioritizes STUNNING VISUAL DESIGN, polish and depth, be to the point, explicit and detailed in your response, and adhere to our development process.
2525
Enhance the user's request and expand on it, think creatively, be ambitious and come up with a very beautiful, elegant, feature complete and polished design. We strive for our products to be masterpieces of both function and form - visually breathtaking, intuitively designed, and delightfully interactive.
2626
27-
**REMEMBER: This is not a toy or demo project. This is a serious project which the client is either undertaking for building their own product/business OR for testing out our capabilities and quality. We do not just expect an MVP, We expect a production-ready, polished, and exceptional solution**
27+
**REMEMBER: This is not a toy or educational project. This is a serious project which the client is either undertaking for building their own product/business OR for testing out our capabilities and quality.**
28+
**Keep the size and complexity of blueprint proportional to the size and complexity of the project.** eg, No need to overengineer a 'todo' app.
2829
</TASK>
2930
3031
<GOAL>
@@ -35,7 +36,6 @@ const SYSTEM_PROMPT = `<ROLE>
3536
**VISUAL DESIGN EXCELLENCE**: Design the application frontend with exceptional attention to visual details - specify exact components, navigation patterns, headers, footers, color schemes, typography scales, spacing systems, micro-interactions, animations, hover states, loading states, and responsive behaviors.
3637
**USER EXPERIENCE FOCUS**: Plan intuitive user flows, clear information hierarchy, accessible design patterns, and delightful interactions that make users want to use the application.
3738
Build upon the provided template. Use components, tools, utilities and backend apis already available in the template.
38-
Think and **BREAKDOWN** The project into multiple incremental phases that build upon each other to create a complete, polished product following our <PHASES GENERATION STRATEGY>.
3939
</GOAL>
4040
4141
<INSTRUCTIONS>
@@ -100,6 +100,7 @@ const SYSTEM_PROMPT = `<ROLE>
100100
✅ Icon libraries: lucide-react, heroicons (specify in frameworks)
101101
❌ Never: .png, .jpg, .svg, .gif files in phase files list
102102
Binary files cannot be generated. Always use the approaches above for visual content.
103+
Do not recommend installing \`cloudflare:workers\` or \`cloudflare:durable-objects\` as dependencies, these are already installed in the project always.
103104
</INSTRUCTIONS>
104105
105106
<KEY GUIDELINES>
@@ -239,11 +240,14 @@ export async function generateBlueprint({ env, inferenceContext, query, language
239240
stream: stream,
240241
});
241242

242-
if (results) {
243-
// Filter and remove any pdf files
244-
results.initialPhase.files = results.initialPhase.files.filter(f => !f.path.endsWith('.pdf'));
243+
if (!results) {
244+
logger.error('Blueprint generation returned no result after all retries');
245+
throw new Error('Failed to generate blueprint: inference returned null');
245246
}
246247

248+
// Filter and remove any pdf files
249+
results.initialPhase.files = results.initialPhase.files.filter(f => !f.path.endsWith('.pdf'));
250+
247251
// // A hack
248252
// if (results?.initialPhase) {
249253
// results.initialPhase.lastPhase = false;

worker/agents/planning/templateSelector.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function selectTemplate({ env, query, availableTemplates, inference
3535
templateCount: availableTemplates.length
3636
});
3737

38-
availableTemplates = availableTemplates.filter(t => t.projectType !== 'presentation');
38+
availableTemplates = availableTemplates.filter(t => t.projectType !== 'presentation' && !t.disabled && !t.name.includes('minimal'));
3939
const validTemplateNames = availableTemplates.map(t => t.name);
4040

4141
const templateDescriptions = availableTemplates.map((t, index) =>
@@ -128,6 +128,11 @@ ENTROPY SEED: ${generateSecureToken(64)} - for unique results`;
128128
maxTokens: 2000,
129129
});
130130

131+
if (!selection) {
132+
logger.error('Template selection returned no result after all retries');
133+
throw new Error('Failed to select template: inference returned null');
134+
}
135+
131136
logger.info(`AI template selection result: ${selection.selectedTemplateName || 'None'}, Reasoning: ${selection.reasoning}`);
132137
return selection;
133138

worker/agents/prompts.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ Template Usage Instructions:
7070
${template.description.usage}
7171
7272
<DO NOT TOUCH FILES>
73-
These files are forbidden to be modified. Do not touch them under any circumstances.
73+
These files are forbidden to be modified. Do not touch them under any circumstances. Doing so will break the application.
7474
${(template.dontTouchFiles ?? []).join('\n')}
75+
worker/core-utils.ts
7576
</DO NOT TOUCH FILES>
7677
7778
<REDACTED FILES>
@@ -888,6 +889,7 @@ COMMON_PITFALLS: `<AVOID COMMON PITFALLS>
888889
Applying this rule to your situation will fix both the type-check errors and the browser's runtime error.
889890
890891
# Never write image files! Never write jpeg, png, svg, etc files yourself! Always use some image url from the web.
892+
**Do not recommend installing \`cloudflare:workers\` or \`cloudflare:durable-objects\` as dependencies, these are already installed in the project always.**
891893
892894
</AVOID COMMON PITFALLS>`,
893895
COMMON_DEP_DOCUMENTATION: `<COMMON DEPENDENCY DOCUMENTATION>
@@ -1368,7 +1370,7 @@ export function issuesPromptFormatter(issues: IssueReport): string {
13681370
13691371
### 1. CRITICAL RUNTIME ERRORS (Fix First - Deployment Blockers)
13701372
**Error Count:** ${issues.runtimeErrors?.length || 0} runtime errors detected
1371-
**Contains Render Loops:** ${runtimeErrorsText.includes('Maximum update depth') || runtimeErrorsText.includes('Too many re-renders') ? 'YES - HIGHEST PRIORITY' : 'No'}
1373+
**Contains Render Loops:** ${runtimeErrorsText.includes('Maximum update depth') || runtimeErrorsText.includes('Too many re-renders') || runtimeErrorsText.includes('infinite loop') ? 'YES - HIGHEST PRIORITY' : 'No'}
13721374
13731375
${runtimeErrorsText || 'No runtime errors detected'}
13741376

worker/services/sandbox/BaseSandboxService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export abstract class BaseSandboxService {
9292
language: t.language,
9393
frameworks: t.frameworks || [],
9494
description: t.description,
95+
disabled: t.disabled ?? false,
9596
projectType: t.projectType || 'app',
9697
renderMode: t.renderMode,
9798
slideDirectory: t.slideDirectory,
@@ -177,6 +178,7 @@ export abstract class BaseSandboxService {
177178
selection: catalogInfo?.description.selection || '',
178179
usage: catalogInfo?.description.usage || ''
179180
},
181+
disabled: catalogInfo?.disabled ?? false,
180182
fileTree,
181183
allFiles: filesMap,
182184
language: catalogInfo?.language,

0 commit comments

Comments
 (0)