/**
* src/managers/PromptManager.ts
*
* Single source of truth for every prompt sent to an LLM.
* Keeping prompts here (not inline in service code) allows tuning
* without touching business logic.
*
* All prompts enforce:
* - Chain of Thought (CoT) via … blocks for Groq
* - The package whitelist (no invented Dart packages)
* - JSON-only output where structured data is required
*/
// ─── Constants ────────────────────────────────────────────────────────────────
/**
* The only Dart packages the LLMs are permitted to use.
* Any other package reference in generated code is considered a hallucination.
*/
export const ALLOWED_DART_PACKAGES = [
'http',
'dio',
'provider',
'shared_preferences',
'flutter_svg',
] as const;
export type AllowedDartPackage = typeof ALLOWED_DART_PACKAGES[number];
// ─── Shared Instruction Blocks ────────────────────────────────────────────────
const PACKAGE_CONSTRAINT = `
════════════════════════════════════════════
CRITICAL — DART PACKAGE WHITELIST
════════════════════════════════════════════
You MUST NOT use any Dart package not in this list:
${ALLOWED_DART_PACKAGES.map(p => ` • ${p}`).join('\n')}
If a feature would normally need another package:
✓ Implement it manually using dart:io, dart:convert, dart:async, etc.
✓ Use Flutter's built-in widgets and APIs.
✗ Do NOT suggest, import, or reference unlisted packages.
════════════════════════════════════════════
`.trim();
const COT_INSTRUCTION = `
Before writing any Dart code, reason through the problem inside tags:
Step 1 — What does this source component DO?
Step 2 — React/JS concepts → Flutter equivalents mapping
Step 3 — State variables: list each, pick Dart type and initial value
Step 4 — Side effects & lifecycle: componentDidMount → initState, etc.
Step 5 — Widget tree structure (top-level → leaf widgets)
Step 6 — API calls: map fetch/axios → Dio service methods
Step 7 — Potential nullability issues to guard against
Only write Dart code AFTER the closing tag.
`.trim();
// ─── PromptManager ────────────────────────────────────────────────────────────
export class PromptManager {
// ═══════════════════════════════════════════════════════════════════════════
// PHASE 4 — Architecture Planning (SambaNova DeepSeek-V3)
// ═══════════════════════════════════════════════════════════════════════════
/**
* Converts a lightweight Skeleton.json into a full Flutter architecture plan.
* The plan drives every subsequent transpilation decision.
*/
static architecturePlanning(skeletonJson: string): string {
return `
You are a senior Flutter architect with 10+ years of experience.
Your task is to design the complete architecture of a Flutter app based on
a Skeleton.json extracted from a React/JavaScript web application.
────────────────────────────────────────────────────────────
INPUT: Skeleton.json
────────────────────────────────────────────────────────────
\`\`\`json
${skeletonJson}
\`\`\`
────────────────────────────────────────────────────────────
OUTPUT: Architecture Plan (JSON only)
────────────────────────────────────────────────────────────
Return a SINGLE valid JSON object with EXACTLY this structure.
Do not include markdown, explanation, or any text outside the JSON.
{
"stateManagement": "provider",
"routing": {
"type": "Navigator 2.0",
"routes": [
{ "name": "RouteName", "path": "/path", "screen": "ScreenName.dart" }
]
},
"screens": [
{
"name": "ScreenName",
"sourceComponents": ["ComponentA", "ComponentB"],
"stateVariables": [
{ "name": "varName", "type": "String", "initialValue": "''" }
],
"apiCalls": [
{ "endpoint": "/api/endpoint", "method": "GET", "responseModel": "ModelName" }
]
}
],
"models": [
{
"name": "ModelName",
"fields": [
{ "name": "fieldName", "type": "DartType" }
]
}
],
"sharedServices": ["api_service.dart", "storage_service.dart"]
}
${PACKAGE_CONSTRAINT}
ARCHITECTURE RULES:
1. State management MUST be "provider" — it is the only whitelisted package.
2. Merge closely related React components into a single Flutter screen.
3. Every screen in "screens" MUST have a corresponding entry in "routes".
4. Extract all network-bound data shapes into "models" with fromJson/toJson.
5. Place all Dio/HTTP calls in "sharedServices", never in widgets.
6. Return ONLY the JSON. Start with { and end with }.
`.trim();
}
// ═══════════════════════════════════════════════════════════════════════════
// PHASE 5a — UI Slicing (SambaNova MiniMax)
// ═══════════════════════════════════════════════════════════════════════════
/**
* Decomposes a JSX component into self-contained sub-components.
* Output is used to better bound LLM context windows during transpilation.
*/
static uiSlicing(componentName: string, jsxCode: string): string {
return `
You are a UI decomposition specialist.
Break down the following JSX component into its minimal self-contained sub-components.
COMPONENT NAME: ${componentName}
JSX SOURCE:
\`\`\`jsx
${jsxCode}
\`\`\`
Return a JSON array. Each element represents one sub-component:
[
{
"name": "SubComponentName",
"props": ["propName: TypeHint"],
"hasState": true,
"stateShape": { "stateVar": "initialValue" },
"rawJsx": "...complete JSX string for this sub-component..."
}
]
RULES:
• Extract ONLY genuinely reusable or structurally distinct pieces.
• If no meaningful sub-components exist, return a single-element array with the component itself.
• Do NOT include import statements in rawJsx.
• rawJsx must be valid, standalone JSX — not a fragment of a fragment.
• Return ONLY the JSON array. Start with [ and end with ].
`.trim();
}
// ═══════════════════════════════════════════════════════════════════════════
// PHASE 5b — JS/JSX → Flutter Transpilation (Groq Llama 3.3 70B)
// ═══════════════════════════════════════════════════════════════════════════
/**
* The primary transpilation prompt. Instructs Groq to convert a JS/JSX chunk
* into production-grade Flutter/Dart code with full CoT reasoning.
*/
static transpileChunk(
chunk: string,
componentName: string,
architecturePlan: string,
chunkType: 'ui' | 'logic' | 'model' | 'service'
): string {
const typeGuidance: Record = {
ui: [
'Translate this JSX into a StatelessWidget or StatefulWidget.',
'Map EVERY HTML tag to the correct Flutter widget (div→Container, span→Text, button→ElevatedButton, img→Image.network, etc.).',
'Replace CSS class-based styling with Flutter BoxDecoration, TextStyle, EdgeInsets, and SizedBox.',
'Map React conditional rendering (&&, ternary) to Flutter conditional widget expression.',
].join('\n '),
logic: [
'Translate this JS logic into a Flutter ChangeNotifier (Provider pattern).',
'useState → instance fields + notifyListeners().',
'useEffect → initState() / dispose() / addListener().',
'useReducer → a simple action-dispatch method pattern.',
].join('\n '),
model: [
'Translate this JS data structure into a Dart model class.',
'Add a factory constructor: factory Model.fromJson(Map json)',
'Add a toJson() method: Map toJson()',
'Use strict null safety — no late variables unless truly needed.',
].join('\n '),
service: [
'Translate this fetch/axios logic into a Dart service class using the `dio` package.',
'Use async/await and proper try/catch with typed DioException handling.',
'Return typed model objects, not raw Map.',
'Inject Dio via constructor for testability.',
].join('\n '),
};
return `
You are an expert Web-to-Flutter transpiler. Your output will be compiled directly
into a production Flutter application.
${COT_INSTRUCTION}
════════════════════════════════════════════
TASK
════════════════════════════════════════════
Component : ${componentName}
Chunk type : ${chunkType}
TYPE-SPECIFIC GUIDANCE:
${typeGuidance[chunkType]}
════════════════════════════════════════════
APP ARCHITECTURE CONTEXT
════════════════════════════════════════════
\`\`\`json
${architecturePlan}
\`\`\`
════════════════════════════════════════════
SOURCE CODE TO TRANSPILE
════════════════════════════════════════════
\`\`\`js
${chunk}
\`\`\`
════════════════════════════════════════════
OUTPUT REQUIREMENTS
════════════════════════════════════════════
${PACKAGE_CONSTRAINT}
DART CODE RULES:
1. Output ONLY valid Dart 3 code with full null safety.
2. First line of the Dart file (after block): // CONFIDENCE: [0-100]
Score reflects how accurately the JS logic was captured.
3. imports: flutter/material.dart first, then dart:* packages, then pub packages.
4. Use const constructors wherever possible.
5. Respect the routing plan in the architecture context for screen navigation.
6. Replace all JS Date/moment logic with Dart's DateTime.
7. localStorage/sessionStorage → shared_preferences package.
8. React context → Provider.of(context) or Consumer.
9. React.memo / useMemo → const widget or cached computation.
10. No placeholder comments like "// TODO: implement". Write real code.
FORMAT:
[Your 7-step reasoning]
// CONFIDENCE: [score]
import 'package:flutter/material.dart';
[rest of complete, compilable Dart file]
`.trim();
}
// ═══════════════════════════════════════════════════════════════════════════
// PHASE 6a — Audit Diff (Gemini 2.0 Flash)
// ═══════════════════════════════════════════════════════════════════════════
/**
* Asks Gemini to diff the JS source against the generated Dart output and
* return a structured list of issues + an optional full corrected file.
*/
static auditDiff(jsSource: string, dartOutput: string, componentName: string): string {
return `
You are a senior code auditor specializing in JavaScript→Flutter transpilation quality.
Perform a deep functional comparison of the JS source and the generated Dart file
for the component named "${componentName}".
════════════════════════════════════════════
JAVASCRIPT SOURCE (ground truth)
════════════════════════════════════════════
\`\`\`js
${jsSource}
\`\`\`
════════════════════════════════════════════
DART OUTPUT (to audit)
════════════════════════════════════════════
\`\`\`dart
${dartOutput}
\`\`\`
════════════════════════════════════════════
OUTPUT: Audit Report (JSON only)
════════════════════════════════════════════
Return a SINGLE JSON object with EXACTLY this shape. No markdown, no explanation.
{
"passed": true,
"confidenceScore": 90,
"issues": [
{
"severity": "critical",
"description": "What is missing or wrong",
"jsReference": "The JS snippet this refers to (≤100 chars)",
"suggestedDartFix": "The corrected Dart code for this specific issue"
}
],
"patch": null
}
AUDIT RULES:
1. Focus ONLY on functional correctness — not style, naming, or indentation.
2. "critical" → Logic that is entirely absent or inverted (will cause wrong behaviour).
3. "warning" → Logic present but subtly incorrect (edge cases, type mismatches).
4. "info" → Minor omissions unlikely to affect functionality.
5. If ALL JS logic is correctly represented in Dart: set passed=true, issues=[], patch=null.
6. If ANY critical issue exists: set passed=false.
The "patch" field MUST then contain the COMPLETE corrected Dart file — not a diff.
7. Return ONLY the JSON. Start with { and end with }.
`.trim();
}
// ═══════════════════════════════════════════════════════════════════════════
// PHASE 6b — Apply Patch (Groq Llama 3.3 70B)
// ═══════════════════════════════════════════════════════════════════════════
/**
* Sends the current Dart code + a list of critical issues back to Groq.
* Groq produces a corrected complete Dart file.
*/
static applyPatch(
dartCode: string,
issues: Array<{ description: string; jsReference: string; suggestedDartFix: string }>,
componentName: string
): string {
const issueBlock = issues
.map((issue, idx) =>
`── Issue ${idx + 1} ──\n` +
`Problem : ${issue.description}\n` +
`JS ref : ${issue.jsReference}\n` +
`Fix :\n${issue.suggestedDartFix}`
)
.join('\n\n');
return `
You are a Flutter code patcher. Apply the required fixes to the Dart file for "${componentName}".
${COT_INSTRUCTION}
════════════════════════════════════════════
CURRENT DART CODE
════════════════════════════════════════════
\`\`\`dart
${dartCode}
\`\`\`
════════════════════════════════════════════
REQUIRED FIXES
════════════════════════════════════════════
${issueBlock}
${PACKAGE_CONSTRAINT}
OUTPUT REQUIREMENTS:
1. Return the COMPLETE corrected Dart file — not just the changed sections.
2. Apply ALL listed fixes. Do not skip any.
3. The file must compile with zero errors under Dart 3 strict null safety.
4. Update the // CONFIDENCE: score at the top to reflect the corrected state.
5. Write code after the closing tag only.
FORMAT:
[Reasoning about each fix]
// CONFIDENCE: [updated score]
[complete corrected Dart file]
`.trim();
}
// ═══════════════════════════════════════════════════════════════════════════
// pubspec.yaml Generation (Groq Llama 3.3 70B)
// ═══════════════════════════════════════════════════════════════════════════
/**
* Generates a minimal, valid pubspec.yaml for the transpiled Flutter project.
*/
static generatePubspec(appName: string, screenNames: string[]): string {
return `
Generate a valid Flutter pubspec.yaml file for an app named "${appName}".
The app has the following screens: ${screenNames.join(', ')}.
${PACKAGE_CONSTRAINT}
RULES:
1. Only include packages from the whitelist that are ACTUALLY needed.
2. Use the latest stable versions.
3. Include the flutter section with uses-material-design: true.
4. SDK constraint: ">=3.0.0 <4.0.0".
5. Return ONLY the raw YAML — no markdown fences, no explanation.
6. The first line must be: name: ${appName.toLowerCase().replace(/[^a-z0-9]/g, '_')}
`.trim();
}
}