Spaces:
Build error
Build error
| /** | |
| * @license | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| /* tslint:disable */ | |
| import {GoogleGenAI} from '@google/genai'; | |
| import {APP_DEFINITIONS_CONFIG, getSystemPrompt} from '../constants'; // Import getSystemPrompt and APP_DEFINITIONS_CONFIG | |
| import {InteractionData} from '../types'; | |
| if (!process.env.API_KEY) { | |
| // This is a critical error. In a real app, you might throw or display a persistent error. | |
| // For this environment, logging to console is okay, but the app might not function. | |
| console.error( | |
| 'API_KEY environment variable is not set. The application will not be able to connect to the Gemini API.', | |
| ); | |
| } | |
| const ai = new GoogleGenAI({apiKey: process.env.API_KEY!}); // The "!" asserts API_KEY is non-null after the check. | |
| export async function* streamAppContent( | |
| interactionHistory: InteractionData[], | |
| currentMaxHistoryLength: number, // Receive current max history length | |
| ): AsyncGenerator<string, void, void> { | |
| const model = 'gemini-2.5-flash-lite-preview-06-17'; // Updated model | |
| if (!process.env.API_KEY) { | |
| yield `<div class="p-4 text-red-700 bg-red-100 rounded-lg"> | |
| <p class="font-bold text-lg">Configuration Error</p> | |
| <p class="mt-2">The API_KEY is not configured. Please set the API_KEY environment variable.</p> | |
| </div>`; | |
| return; | |
| } | |
| if (interactionHistory.length === 0) { | |
| yield `<div class="p-4 text-orange-700 bg-orange-100 rounded-lg"> | |
| <p class="font-bold text-lg">No interaction data provided.</p> | |
| </div>`; | |
| return; | |
| } | |
| const systemPrompt = getSystemPrompt(currentMaxHistoryLength); // Generate system prompt dynamically | |
| const currentInteraction = interactionHistory[0]; | |
| // pastInteractions already respects currentMaxHistoryLength due to slicing in App.tsx | |
| const pastInteractions = interactionHistory.slice(1); | |
| const currentElementName = | |
| currentInteraction.elementText || | |
| currentInteraction.id || | |
| 'Unknown Element'; | |
| let currentInteractionSummary = `Current User Interaction: Clicked on '${currentElementName}' (Type: ${currentInteraction.type || 'N/A'}, ID: ${currentInteraction.id || 'N/A'}).`; | |
| if (currentInteraction.value) { | |
| currentInteractionSummary += ` Associated value: '${currentInteraction.value.substring(0, 100)}'.`; | |
| } | |
| const currentAppDef = APP_DEFINITIONS_CONFIG.find( | |
| (app) => app.id === currentInteraction.appContext, | |
| ); | |
| const currentAppContext = currentInteraction.appContext | |
| ? `Current App Context: '${currentAppDef?.name || currentInteraction.appContext}'.` | |
| : 'No specific app context for current interaction.'; | |
| let historyPromptSegment = ''; | |
| if (pastInteractions.length > 0) { | |
| // The number of previous interactions to mention in the prompt text. | |
| const numPrevInteractionsToMention = | |
| currentMaxHistoryLength - 1 > 0 ? currentMaxHistoryLength - 1 : 0; | |
| historyPromptSegment = `\n\nPrevious User Interactions (up to ${numPrevInteractionsToMention} most recent, oldest first in this list segment but chronologically before current):`; | |
| // Iterate over the pastInteractions array, which is already correctly sized | |
| pastInteractions.forEach((interaction, index) => { | |
| const pastElementName = | |
| interaction.elementText || interaction.id || 'Unknown Element'; | |
| const appDef = APP_DEFINITIONS_CONFIG.find( | |
| (app) => app.id === interaction.appContext, | |
| ); | |
| const appName = interaction.appContext | |
| ? appDef?.name || interaction.appContext | |
| : 'N/A'; | |
| historyPromptSegment += `\n${index + 1}. (App: ${appName}) Clicked '${pastElementName}' (Type: ${interaction.type || 'N/A'}, ID: ${interaction.id || 'N/A'})`; | |
| if (interaction.value) { | |
| historyPromptSegment += ` with value '${interaction.value.substring(0, 50)}'`; | |
| } | |
| historyPromptSegment += '.'; | |
| }); | |
| } | |
| const fullPrompt = `${systemPrompt} | |
| ${currentInteractionSummary} | |
| ${currentAppContext} | |
| ${historyPromptSegment} | |
| Full Context for Current Interaction (for your reference, primarily use summaries and history): | |
| ${JSON.stringify(currentInteraction, null, 1)} | |
| Generate the HTML content for the window's content area only:`; | |
| try { | |
| const response = await ai.models.generateContentStream({ | |
| model: model, | |
| contents: fullPrompt, | |
| // Removed thinkingConfig to use default (enabled thinking) for higher quality responses | |
| // as this is a general app, not a low-latency game AI. | |
| config: {}, | |
| }); | |
| for await (const chunk of response) { | |
| if (chunk.text) { | |
| // Ensure text property exists and is not empty | |
| yield chunk.text; | |
| } | |
| } | |
| } catch (error) { | |
| console.error('Error streaming from Gemini:', error); | |
| let errorMessage = 'An error occurred while generating content.'; | |
| // Check if error is an instance of Error and has a message property | |
| if (error instanceof Error && typeof error.message === 'string') { | |
| errorMessage += ` Details: ${error.message}`; | |
| } else if ( | |
| typeof error === 'object' && | |
| error !== null && | |
| 'message' in error && | |
| typeof (error as any).message === 'string' | |
| ) { | |
| // Handle cases where error might be an object with a message property (like the API error object) | |
| errorMessage += ` Details: ${(error as any).message}`; | |
| } else if (typeof error === 'string') { | |
| errorMessage += ` Details: ${error}`; | |
| } | |
| yield `<div class="p-4 text-red-700 bg-red-100 rounded-lg"> | |
| <p class="font-bold text-lg">Error Generating Content</p> | |
| <p class="mt-2">${errorMessage}</p> | |
| <p class="mt-1">This may be due to an API key issue, network problem, or misconfiguration. Please check the developer console for more details.</p> | |
| </div>`; | |
| } | |
| } | |