import os import json import requests from flask import Blueprint, jsonify, request from flask_login import login_required llm = Blueprint('llm', __name__) def _generate_script_from_natural_language(natural_query): """Generates a Javascript function from natural language using Gemini REST API.""" gemni_model = os.environ.get("GEMINI_MODEL", "gemini-1.5-flash") api_key = os.environ.get("GEMINI_API_KEY") if not api_key: return None, "GEMINI_API_KEY environment variable not set." api_url = f"https://generativelanguage.googleapis.com/v1beta/models/{gemni_model}:generateContent?key={api_key}" headers = {'Content-Type': 'application/json'} try: prompt = f""" You are an expert Javascript developer. Your task is to write a complete, production-ready Javascript async function based on the user's request. **Function Signature:** Your function MUST have the following signature: `async (req, environment) => {{ ... }}` - `req`: An object containing details about the incoming HTTP request (e.g., `req.method`, `req.headers`, `req.body`, `req.query`). - `environment`: A mutable JSON object that persists across executions. You can read and write to it to maintain state. **Environment & Constraints:** - The function will be executed in a simple, sandboxed Javascript environment. - **CRITICAL**: ALL helper functions or variables MUST be defined *inside* the main `async` function. Do not define anything in the global scope. - **DO NOT** use `require()`, `import`, or any other module loading system. - **DO NOT** access the file system (`fs` module) or make network requests. - You have access to a `console.log()` function for logging. **Response Helpers:** You must use one of the following functions to return a response: - `HtmlResponse(body)`: Returns an HTML response. - `JsonResponse(body)`: Returns a JSON response. - `TextResponse(body)`: Returns a plain text response. - `RedirectResponse(url)`: Redirects the user. **Complex Example (Tic-Tac-Toe):** ```javascript async (req, environment) => {{ // Helper function defined INSIDE the main function function checkWinner(board) {{ const winConditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; for (const condition of winConditions) {{ const [a, b, c] = condition; if (board[a] && board[a] === board[b] && board[a] === board[c]) {{ return board[a]; }} }} return null; }} if (!environment.board) {{ environment.board = Array(9).fill(""); environment.turn = "X"; environment.winner = null; }} if (req.method === "POST" && req.json && req.json.move !== undefined) {{ const move = parseInt(req.json.move); if (environment.board[move] === "" && !environment.winner) {{ environment.board[move] = environment.turn; environment.turn = environment.turn === "X" ? "O" : "X"; environment.winner = checkWinner(environment.board); }} }} const boardHTML = environment.board.map((cell, index) => ``).join(""); const message = environment.winner ? `Player ${{environment.winner}} wins!` : `Turn: ${{environment.turn}}`; return HtmlResponse(` Tic-Tac-Toe

${{message}}

${{boardHTML}}
`); }} ``` **User's request:** "{natural_query}" Return ONLY the complete Javascript function code, without any explanation, comments, or surrounding text/markdown. """ payload = json.dumps({ "contents": [{"parts": [{"text": prompt}]}] }) response = requests.post(api_url, headers=headers, data=payload) response.raise_for_status() response_data = response.json() candidates = response_data.get('candidates', []) if not candidates: return None, "No candidates found in API response." content = candidates[0].get('content', {}) parts = content.get('parts', []) if not parts: return None, "No parts found in API response content." generated_script = parts[0].get('text', '').strip() # More robustly extract from markdown if generated_script.startswith("```javascript"): generated_script = generated_script[12:] if generated_script.endswith("```"): generated_script = generated_script[:-3] generated_script = generated_script.strip() # Remove any leading non-code characters if not generated_script.startswith('async ('): async_start = generated_script.find('async (') if async_start != -1: generated_script = generated_script[async_start:] return generated_script.strip(), None except requests.exceptions.RequestException as e: return None, f"Error communicating with API: {e}" except (KeyError, IndexError, Exception) as e: return None, f"Error processing API response: {e}" @llm.route("/generate_script", methods=["POST"]) @login_required def generate_script(): try: natural_query = request.json.get('natural_query') if not natural_query: return jsonify({"error": "natural_query is required"}), 400 script_content, error = _generate_script_from_natural_language(natural_query) if error: return jsonify({"error": error}), 500 return jsonify({"script_content": script_content}) except Exception as e: return jsonify({'error': str(e)}), 500