blob: 057d9d68e6a0abe1be675fd11f5b3137e19f1f61 [file] [log] [blame]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:google_generative_ai/google_generative_ai.dart';
import 'code_processor.dart';
import 'context.dart';
import 'prompts.dart';
Future<String> dartifyNativeCode(String sourceCode, Context context) async {
final apiKey = Platform.environment['GEMINI_API_KEY'];
if (apiKey == null) {
stderr.writeln(r'No $GEMINI_API_KEY environment variable');
exit(1);
}
final model = GenerativeModel(
model: 'gemini-2.0-flash',
apiKey: apiKey,
generationConfig: GenerationConfig(
temperature: 0,
topK: 64,
topP: 0.95,
maxOutputTokens: 8192,
responseMimeType: 'application/json',
),
);
final translatePrompt = TranslatePrompt(
sourceCode,
await context.toDartLikeRepresentation(sourceCode),
);
final chatSession = model.startChat();
final response = await chatSession.sendMessage(
Content.text(translatePrompt.prompt),
);
var mainCode = translatePrompt.getParsedResponse(response.text ?? '');
var helperCode = '';
final codeProcessor = CodeProcessor();
mainCode = codeProcessor.addImports(mainCode, [
...context.importedPackages,
context.bindingsFileAbsolutePath,
]);
var bestResult = mainCode;
var currentBestErrorCount = double.maxFinite.toInt();
for (var i = 0; i < 3; i++) {
final errorMessages = await codeProcessor.analyzeCode(mainCode, helperCode);
final errorMessage = errorMessages.join('\n\n');
final numberOfErrors = errorMessages.length;
if (numberOfErrors < currentBestErrorCount) {
currentBestErrorCount = numberOfErrors;
bestResult = mainCode;
if (numberOfErrors == 0) {
break;
}
}
stderr.writeln('Dart analysis found issues: $errorMessage');
final fixPrompt = FixPrompt(mainCode, helperCode, errorMessage);
final fixResponse = await chatSession.sendMessage(
Content.text(fixPrompt.prompt),
);
final fixedCode = fixPrompt.getParsedResponse(fixResponse.text ?? '');
mainCode = fixedCode.mainCode;
helperCode = fixedCode.helperCode;
}
bestResult = codeProcessor.removeHelperCodeImport(mainCode);
return bestResult;
}