titan-server / src /managers /PromptManager.ts
M-hv1's picture
Upload 3 files
c6ec6e8 verified
Raw
History Blame Contribute Delete
19 kB
/**
* 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 <think>…</think> 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 <think> tags:
<think>
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
</think>
Only write Dart code AFTER the closing </think> 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<typeof chunkType, string> = {
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<String, dynamic> json)',
'Add a toJson() method: Map<String, dynamic> 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<String, dynamic>.',
'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 <think> 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<T>(context) or Consumer<T>.
9. React.memo / useMemo β†’ const widget or cached computation.
10. No placeholder comments like "// TODO: implement". Write real code.
FORMAT:
<think>
[Your 7-step reasoning]
</think>
// 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 </think> tag only.
FORMAT:
<think>
[Reasoning about each fix]
</think>
// 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();
}
}