khulnasoft commited on
Commit
bc8d68d
·
verified ·
1 Parent(s): b5e7016

Create geminiService.tsx

Browse files
Files changed (1) hide show
  1. geminiService.tsx +138 -0
geminiService.tsx ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /* tslint:disable */
6
+ import {GoogleGenAI} from '@google/genai';
7
+ import {APP_DEFINITIONS_CONFIG, getSystemPrompt} from '../constants'; // Import getSystemPrompt and APP_DEFINITIONS_CONFIG
8
+ import {InteractionData} from '../types';
9
+
10
+ if (!process.env.API_KEY) {
11
+ // This is a critical error. In a real app, you might throw or display a persistent error.
12
+ // For this environment, logging to console is okay, but the app might not function.
13
+ console.error(
14
+ 'API_KEY environment variable is not set. The application will not be able to connect to the Gemini API.',
15
+ );
16
+ }
17
+
18
+ const ai = new GoogleGenAI({apiKey: process.env.API_KEY!}); // The "!" asserts API_KEY is non-null after the check.
19
+
20
+ export async function* streamAppContent(
21
+ interactionHistory: InteractionData[],
22
+ currentMaxHistoryLength: number, // Receive current max history length
23
+ ): AsyncGenerator<string, void, void> {
24
+ const model = 'gemini-2.5-flash-lite-preview-06-17'; // Updated model
25
+
26
+ if (!process.env.API_KEY) {
27
+ yield `<div class="p-4 text-red-700 bg-red-100 rounded-lg">
28
+ <p class="font-bold text-lg">Configuration Error</p>
29
+ <p class="mt-2">The API_KEY is not configured. Please set the API_KEY environment variable.</p>
30
+ </div>`;
31
+ return;
32
+ }
33
+
34
+ if (interactionHistory.length === 0) {
35
+ yield `<div class="p-4 text-orange-700 bg-orange-100 rounded-lg">
36
+ <p class="font-bold text-lg">No interaction data provided.</p>
37
+ </div>`;
38
+ return;
39
+ }
40
+
41
+ const systemPrompt = getSystemPrompt(currentMaxHistoryLength); // Generate system prompt dynamically
42
+
43
+ const currentInteraction = interactionHistory[0];
44
+ // pastInteractions already respects currentMaxHistoryLength due to slicing in App.tsx
45
+ const pastInteractions = interactionHistory.slice(1);
46
+
47
+ const currentElementName =
48
+ currentInteraction.elementText ||
49
+ currentInteraction.id ||
50
+ 'Unknown Element';
51
+ let currentInteractionSummary = `Current User Interaction: Clicked on '${currentElementName}' (Type: ${currentInteraction.type || 'N/A'}, ID: ${currentInteraction.id || 'N/A'}).`;
52
+ if (currentInteraction.value) {
53
+ currentInteractionSummary += ` Associated value: '${currentInteraction.value.substring(0, 100)}'.`;
54
+ }
55
+
56
+ const currentAppDef = APP_DEFINITIONS_CONFIG.find(
57
+ (app) => app.id === currentInteraction.appContext,
58
+ );
59
+ const currentAppContext = currentInteraction.appContext
60
+ ? `Current App Context: '${currentAppDef?.name || currentInteraction.appContext}'.`
61
+ : 'No specific app context for current interaction.';
62
+
63
+ let historyPromptSegment = '';
64
+ if (pastInteractions.length > 0) {
65
+ // The number of previous interactions to mention in the prompt text.
66
+ const numPrevInteractionsToMention =
67
+ currentMaxHistoryLength - 1 > 0 ? currentMaxHistoryLength - 1 : 0;
68
+ historyPromptSegment = `\n\nPrevious User Interactions (up to ${numPrevInteractionsToMention} most recent, oldest first in this list segment but chronologically before current):`;
69
+
70
+ // Iterate over the pastInteractions array, which is already correctly sized
71
+ pastInteractions.forEach((interaction, index) => {
72
+ const pastElementName =
73
+ interaction.elementText || interaction.id || 'Unknown Element';
74
+ const appDef = APP_DEFINITIONS_CONFIG.find(
75
+ (app) => app.id === interaction.appContext,
76
+ );
77
+ const appName = interaction.appContext
78
+ ? appDef?.name || interaction.appContext
79
+ : 'N/A';
80
+ historyPromptSegment += `\n${index + 1}. (App: ${appName}) Clicked '${pastElementName}' (Type: ${interaction.type || 'N/A'}, ID: ${interaction.id || 'N/A'})`;
81
+ if (interaction.value) {
82
+ historyPromptSegment += ` with value '${interaction.value.substring(0, 50)}'`;
83
+ }
84
+ historyPromptSegment += '.';
85
+ });
86
+ }
87
+
88
+ const fullPrompt = `${systemPrompt}
89
+
90
+ ${currentInteractionSummary}
91
+ ${currentAppContext}
92
+ ${historyPromptSegment}
93
+
94
+ Full Context for Current Interaction (for your reference, primarily use summaries and history):
95
+ ${JSON.stringify(currentInteraction, null, 1)}
96
+
97
+ Generate the HTML content for the window's content area only:`;
98
+
99
+ try {
100
+ const response = await ai.models.generateContentStream({
101
+ model: model,
102
+ contents: fullPrompt,
103
+ // Removed thinkingConfig to use default (enabled thinking) for higher quality responses
104
+ // as this is a general app, not a low-latency game AI.
105
+ config: {},
106
+ });
107
+
108
+ for await (const chunk of response) {
109
+ if (chunk.text) {
110
+ // Ensure text property exists and is not empty
111
+ yield chunk.text;
112
+ }
113
+ }
114
+ } catch (error) {
115
+ console.error('Error streaming from Gemini:', error);
116
+ let errorMessage = 'An error occurred while generating content.';
117
+ // Check if error is an instance of Error and has a message property
118
+ if (error instanceof Error && typeof error.message === 'string') {
119
+ errorMessage += ` Details: ${error.message}`;
120
+ } else if (
121
+ typeof error === 'object' &&
122
+ error !== null &&
123
+ 'message' in error &&
124
+ typeof (error as any).message === 'string'
125
+ ) {
126
+ // Handle cases where error might be an object with a message property (like the API error object)
127
+ errorMessage += ` Details: ${(error as any).message}`;
128
+ } else if (typeof error === 'string') {
129
+ errorMessage += ` Details: ${error}`;
130
+ }
131
+
132
+ yield `<div class="p-4 text-red-700 bg-red-100 rounded-lg">
133
+ <p class="font-bold text-lg">Error Generating Content</p>
134
+ <p class="mt-2">${errorMessage}</p>
135
+ <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>
136
+ </div>`;
137
+ }
138
+ }