/** * 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(); } }