mcp-hydrocoder-image 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +454 -0
- package/bin/install-skills.js +115 -0
- package/dist/api/geminiClient.d.ts +57 -0
- package/dist/api/geminiClient.d.ts.map +1 -0
- package/dist/api/geminiClient.js +341 -0
- package/dist/api/geminiClient.js.map +1 -0
- package/dist/api/geminiTextClient.d.ts +44 -0
- package/dist/api/geminiTextClient.d.ts.map +1 -0
- package/dist/api/geminiTextClient.js +202 -0
- package/dist/api/geminiTextClient.js.map +1 -0
- package/dist/business/fileManager.d.ts +20 -0
- package/dist/business/fileManager.d.ts.map +1 -0
- package/dist/business/fileManager.js +76 -0
- package/dist/business/fileManager.js.map +1 -0
- package/dist/business/inputValidator.d.ts +44 -0
- package/dist/business/inputValidator.d.ts.map +1 -0
- package/dist/business/inputValidator.js +213 -0
- package/dist/business/inputValidator.js.map +1 -0
- package/dist/business/responseBuilder.d.ts +21 -0
- package/dist/business/responseBuilder.d.ts.map +1 -0
- package/dist/business/responseBuilder.js +166 -0
- package/dist/business/responseBuilder.js.map +1 -0
- package/dist/business/structuredPromptGenerator.d.ts +56 -0
- package/dist/business/structuredPromptGenerator.d.ts.map +1 -0
- package/dist/business/structuredPromptGenerator.js +218 -0
- package/dist/business/structuredPromptGenerator.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/server/errorHandler.d.ts +29 -0
- package/dist/server/errorHandler.d.ts.map +1 -0
- package/dist/server/errorHandler.js +99 -0
- package/dist/server/errorHandler.js.map +1 -0
- package/dist/server/mcpServer.d.ts +159 -0
- package/dist/server/mcpServer.d.ts.map +1 -0
- package/dist/server/mcpServer.js +434 -0
- package/dist/server/mcpServer.js.map +1 -0
- package/dist/server-main.d.ts +5 -0
- package/dist/server-main.d.ts.map +1 -0
- package/dist/server-main.js +37 -0
- package/dist/server-main.js.map +1 -0
- package/dist/types/mcp.d.ts +121 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +22 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/result.d.ts +27 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +27 -0
- package/dist/types/result.js.map +1 -0
- package/dist/utils/config.d.ts +29 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +56 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/errors.d.ts +84 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +215 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +80 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +186 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/security.d.ts +50 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +116 -0
- package/dist/utils/security.js.map +1 -0
- package/package.json +89 -0
- package/skills/image-generation/SKILL.md +131 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini API client for image generation
|
|
3
|
+
* Integrates with Google's Gemini AI API using the official SDK
|
|
4
|
+
* Supports automatic URL Context processing and feature parameters
|
|
5
|
+
*/
|
|
6
|
+
import { GoogleGenAI } from '@google/genai';
|
|
7
|
+
import { GEMINI_MODELS } from '../types/mcp.js';
|
|
8
|
+
import { Err, Ok } from '../types/result.js';
|
|
9
|
+
import { GeminiAPIError, NetworkError } from '../utils/errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Safely analyze response structure for debugging (removes sensitive data)
|
|
12
|
+
*/
|
|
13
|
+
function analyzeResponseStructure(obj) {
|
|
14
|
+
if (!obj || typeof obj !== 'object') {
|
|
15
|
+
return { type: typeof obj, value: obj };
|
|
16
|
+
}
|
|
17
|
+
const seen = new WeakSet();
|
|
18
|
+
const sanitize = (value, depth = 0) => {
|
|
19
|
+
if (depth > 3)
|
|
20
|
+
return '[max depth]';
|
|
21
|
+
if (value === null || value === undefined)
|
|
22
|
+
return value;
|
|
23
|
+
if (typeof value !== 'object')
|
|
24
|
+
return typeof value === 'string' && value.length > 100
|
|
25
|
+
? `[string length: ${value.length}]`
|
|
26
|
+
: value;
|
|
27
|
+
if (seen.has(value))
|
|
28
|
+
return '[circular]';
|
|
29
|
+
seen.add(value);
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
return value.slice(0, 3).map((v) => sanitize(v, depth + 1));
|
|
32
|
+
}
|
|
33
|
+
const record = value;
|
|
34
|
+
const result = {};
|
|
35
|
+
for (const [key, val] of Object.entries(record)) {
|
|
36
|
+
// Skip sensitive keys
|
|
37
|
+
if (/apikey|token|secret|password|credential/i.test(key)) {
|
|
38
|
+
result[key] = '[REDACTED]';
|
|
39
|
+
}
|
|
40
|
+
else if (key === 'data' && typeof val === 'string' && val.length > 100) {
|
|
41
|
+
// Likely base64 image data
|
|
42
|
+
result[key] = `[base64 data, length: ${val.length}]`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
result[key] = sanitize(val, depth + 1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
return sanitize(obj);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Type guard for Gemini response validation
|
|
54
|
+
*/
|
|
55
|
+
function isGeminiResponse(obj) {
|
|
56
|
+
if (!obj || typeof obj !== 'object')
|
|
57
|
+
return false;
|
|
58
|
+
const response = obj;
|
|
59
|
+
// Check if it has response property (wrapped response)
|
|
60
|
+
if ('response' in response && response['response'] && typeof response['response'] === 'object') {
|
|
61
|
+
const innerResponse = response['response'];
|
|
62
|
+
return 'candidates' in innerResponse && Array.isArray(innerResponse['candidates']);
|
|
63
|
+
}
|
|
64
|
+
// Check direct candidates property (direct response)
|
|
65
|
+
return 'candidates' in response && Array.isArray(response['candidates']);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Implementation of Gemini API client
|
|
69
|
+
*/
|
|
70
|
+
class GeminiClientImpl {
|
|
71
|
+
constructor(genai, defaultQuality = 'fast') {
|
|
72
|
+
this.genai = genai;
|
|
73
|
+
this.defaultQuality = defaultQuality;
|
|
74
|
+
}
|
|
75
|
+
async generateImage(params) {
|
|
76
|
+
try {
|
|
77
|
+
// Prepare the request content with proper structure for multimodal input
|
|
78
|
+
const requestContent = [];
|
|
79
|
+
// Structure the contents properly for image generation/editing
|
|
80
|
+
// Priority: inputImages > inputImage > text-only
|
|
81
|
+
if (params.inputImages && params.inputImages.length > 0) {
|
|
82
|
+
// For multi-image: multiple inlineData parts + text
|
|
83
|
+
const parts = params.inputImages.map((img) => ({
|
|
84
|
+
inlineData: {
|
|
85
|
+
data: img.data,
|
|
86
|
+
mimeType: img.mimeType,
|
|
87
|
+
},
|
|
88
|
+
}));
|
|
89
|
+
parts.push({ text: params.prompt });
|
|
90
|
+
requestContent.push({ parts });
|
|
91
|
+
}
|
|
92
|
+
else if (params.inputImage) {
|
|
93
|
+
// For image editing: provide image first, then text instructions
|
|
94
|
+
requestContent.push({
|
|
95
|
+
parts: [
|
|
96
|
+
{
|
|
97
|
+
inlineData: {
|
|
98
|
+
data: params.inputImage,
|
|
99
|
+
mimeType: params.inputImageMimeType || 'image/jpeg',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
text: params.prompt,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// For text-to-image: provide only text prompt
|
|
110
|
+
requestContent.push({
|
|
111
|
+
parts: [
|
|
112
|
+
{
|
|
113
|
+
text: params.prompt,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// Determine effective quality
|
|
119
|
+
const effectiveQuality = params.quality ?? this.defaultQuality;
|
|
120
|
+
// Select model based on quality preset
|
|
121
|
+
const modelName = effectiveQuality === 'quality' ? GEMINI_MODELS.PRO : GEMINI_MODELS.FLASH;
|
|
122
|
+
// Construct config object for generateContent
|
|
123
|
+
const imageConfig = {};
|
|
124
|
+
if (params.aspectRatio) {
|
|
125
|
+
imageConfig['aspectRatio'] = params.aspectRatio;
|
|
126
|
+
}
|
|
127
|
+
if (params.imageSize) {
|
|
128
|
+
imageConfig['imageSize'] = params.imageSize;
|
|
129
|
+
}
|
|
130
|
+
// Build config with optional thinkingConfig
|
|
131
|
+
const thinkingConfig = effectiveQuality === 'balanced' ? { thinkingConfig: { thinkingLevel: 'high' } } : {};
|
|
132
|
+
const config = {
|
|
133
|
+
...(Object.keys(imageConfig).length > 0 && { imageConfig }),
|
|
134
|
+
responseModalities: ['IMAGE'],
|
|
135
|
+
...thinkingConfig,
|
|
136
|
+
};
|
|
137
|
+
// Construct tools array for Google Search grounding
|
|
138
|
+
const tools = params.useGoogleSearch ? [{ googleSearch: {} }] : undefined;
|
|
139
|
+
// Generate content using Gemini API
|
|
140
|
+
const rawResponse = await this.genai.models.generateContent({
|
|
141
|
+
model: modelName,
|
|
142
|
+
contents: requestContent,
|
|
143
|
+
config,
|
|
144
|
+
...(tools && { tools }),
|
|
145
|
+
});
|
|
146
|
+
// Validate response structure with type guard
|
|
147
|
+
if (!isGeminiResponse(rawResponse)) {
|
|
148
|
+
const responseStructure = analyzeResponseStructure(rawResponse);
|
|
149
|
+
// Check if it's an error response from Gemini
|
|
150
|
+
const asRecord = rawResponse;
|
|
151
|
+
if (asRecord['error']) {
|
|
152
|
+
const error = asRecord['error'];
|
|
153
|
+
return Err(new GeminiAPIError(`Gemini API Error: ${error['message'] || 'Unknown error'}`, {
|
|
154
|
+
code: error['code'],
|
|
155
|
+
status: error['status'],
|
|
156
|
+
details: error['details'] || responseStructure,
|
|
157
|
+
stage: 'api_error',
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
return Err(new GeminiAPIError('Invalid response structure from Gemini API', {
|
|
161
|
+
message: 'The API returned an unexpected response format',
|
|
162
|
+
responseStructure: responseStructure,
|
|
163
|
+
stage: 'response_validation',
|
|
164
|
+
suggestion: 'Check if the API endpoint or model configuration is correct',
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
// Extract the actual response data (handle wrapped responses)
|
|
168
|
+
const responseData = rawResponse['response']
|
|
169
|
+
? rawResponse['response']
|
|
170
|
+
: rawResponse;
|
|
171
|
+
// Check for prompt feedback (safety blocking)
|
|
172
|
+
const responseAsRecord = responseData;
|
|
173
|
+
if (responseAsRecord['promptFeedback']) {
|
|
174
|
+
const promptFeedback = responseAsRecord['promptFeedback'];
|
|
175
|
+
if (promptFeedback['blockReason'] === 'SAFETY') {
|
|
176
|
+
return Err(new GeminiAPIError('Image generation blocked for safety reasons', {
|
|
177
|
+
stage: 'prompt_analysis',
|
|
178
|
+
blockReason: promptFeedback['blockReason'],
|
|
179
|
+
suggestion: 'Rephrase your prompt to avoid potentially sensitive content',
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
if (promptFeedback['blockReason'] === 'OTHER' ||
|
|
183
|
+
promptFeedback['blockReason'] === 'PROHIBITED_CONTENT') {
|
|
184
|
+
return Err(new GeminiAPIError('Image generation blocked due to prohibited content', {
|
|
185
|
+
stage: 'prompt_analysis',
|
|
186
|
+
blockReason: promptFeedback['blockReason'],
|
|
187
|
+
suggestion: 'Remove any prohibited content from your prompt and try again',
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Check for candidates
|
|
192
|
+
if (!responseData.candidates || responseData.candidates.length === 0) {
|
|
193
|
+
return Err(new GeminiAPIError('No image generated: Content may have been filtered', {
|
|
194
|
+
stage: 'generation',
|
|
195
|
+
candidatesCount: 0,
|
|
196
|
+
suggestion: 'Try rephrasing your prompt to avoid potentially sensitive content',
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
const candidate = responseData.candidates[0];
|
|
200
|
+
if (!candidate || !candidate.content || !candidate.content.parts) {
|
|
201
|
+
return Err(new GeminiAPIError('No valid content in response', {
|
|
202
|
+
stage: 'candidate_extraction',
|
|
203
|
+
suggestion: 'The API response was incomplete. Please try again',
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
const parts = candidate.content.parts;
|
|
207
|
+
// Handle finish reason specific errors before checking parts
|
|
208
|
+
if (candidate.finishReason) {
|
|
209
|
+
const finishReason = candidate.finishReason;
|
|
210
|
+
if (finishReason === 'IMAGE_SAFETY') {
|
|
211
|
+
return Err(new GeminiAPIError('Image generation stopped for safety reasons', {
|
|
212
|
+
finishReason,
|
|
213
|
+
stage: 'generation_stopped',
|
|
214
|
+
suggestion: 'Modify your prompt to avoid potentially sensitive content',
|
|
215
|
+
safetyRatings: candidate['safetyRatings']
|
|
216
|
+
? candidate['safetyRatings']
|
|
217
|
+
?.map((rating) => {
|
|
218
|
+
const category = rating['category']
|
|
219
|
+
.replace('HARM_CATEGORY_', '')
|
|
220
|
+
.split('_')
|
|
221
|
+
.map((word) => word.charAt(0) + word.slice(1).toLowerCase())
|
|
222
|
+
.join(' ');
|
|
223
|
+
return `${category} (${rating['blocked'] ? 'BLOCKED' : 'ALLOWED'})`;
|
|
224
|
+
})
|
|
225
|
+
.join(', ')
|
|
226
|
+
: undefined,
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
if (finishReason === 'MAX_TOKENS') {
|
|
230
|
+
return Err(new GeminiAPIError('Maximum token limit reached during generation', {
|
|
231
|
+
finishReason,
|
|
232
|
+
stage: 'generation_stopped',
|
|
233
|
+
suggestion: 'Try using a shorter or simpler prompt',
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (parts.length === 0) {
|
|
238
|
+
return Err(new GeminiAPIError('No content parts in response', {
|
|
239
|
+
stage: 'content_extraction',
|
|
240
|
+
suggestion: 'The generation was incomplete. Please try again',
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
// Check if we got an image or text (error message)
|
|
244
|
+
const imagePart = parts.find((part) => part.inlineData?.data);
|
|
245
|
+
const textPart = parts.find((part) => part.text);
|
|
246
|
+
if (!imagePart?.inlineData) {
|
|
247
|
+
// If there's text, it's likely an error message from Gemini
|
|
248
|
+
const errorMessage = textPart?.text || 'Image generation failed';
|
|
249
|
+
return Err(new GeminiAPIError('Image generation failed due to content filtering', {
|
|
250
|
+
reason: errorMessage,
|
|
251
|
+
stage: 'image_extraction',
|
|
252
|
+
suggestion: 'The prompt was blocked by safety filters. Try rephrasing your prompt to avoid potentially sensitive content.',
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
// Convert base64 image data to Buffer
|
|
256
|
+
const imageBuffer = Buffer.from(imagePart.inlineData.data, 'base64');
|
|
257
|
+
const mimeType = imagePart.inlineData.mimeType || 'image/png';
|
|
258
|
+
// Create metadata
|
|
259
|
+
const metadata = {
|
|
260
|
+
model: modelName,
|
|
261
|
+
prompt: params.prompt,
|
|
262
|
+
mimeType,
|
|
263
|
+
timestamp: new Date(),
|
|
264
|
+
inputImageProvided: !!params.inputImage || !!(params.inputImages && params.inputImages.length > 0),
|
|
265
|
+
...(responseData.modelVersion && { modelVersion: responseData.modelVersion }),
|
|
266
|
+
...(responseData.responseId && { responseId: responseData.responseId }),
|
|
267
|
+
};
|
|
268
|
+
return Ok({
|
|
269
|
+
imageData: imageBuffer,
|
|
270
|
+
metadata,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
return this.handleError(error, params.prompt);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
handleError(error, prompt) {
|
|
278
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
279
|
+
// Check if it's a network error
|
|
280
|
+
if (this.isNetworkError(error)) {
|
|
281
|
+
return Err(new NetworkError(`Network error during image generation: ${errorMessage}`, 'Check your internet connection and try again', error instanceof Error ? error : undefined));
|
|
282
|
+
}
|
|
283
|
+
// Check if it's an API-specific error
|
|
284
|
+
if (this.isAPIError(error)) {
|
|
285
|
+
return Err(new GeminiAPIError(`Failed to generate image: ${errorMessage}`, this.getAPIErrorSuggestion(errorMessage), this.extractStatusCode(error)));
|
|
286
|
+
}
|
|
287
|
+
// Generic API error
|
|
288
|
+
return Err(new GeminiAPIError(`Failed to generate image with prompt "${prompt}": ${errorMessage}`, 'Check your API key, quota, and prompt validity. Try again with a different prompt'));
|
|
289
|
+
}
|
|
290
|
+
isNetworkError(error) {
|
|
291
|
+
if (error instanceof Error) {
|
|
292
|
+
const networkErrorCodes = ['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND'];
|
|
293
|
+
return networkErrorCodes.some((code) => error.message.includes(code) || error.code === code);
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
isAPIError(error) {
|
|
298
|
+
if (error instanceof Error) {
|
|
299
|
+
const apiErrorKeywords = ['quota', 'rate limit', 'unauthorized', 'forbidden', 'api key'];
|
|
300
|
+
return apiErrorKeywords.some((keyword) => error.message.toLowerCase().includes(keyword));
|
|
301
|
+
}
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
getAPIErrorSuggestion(errorMessage) {
|
|
305
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
306
|
+
if (lowerMessage.includes('quota') || lowerMessage.includes('rate limit')) {
|
|
307
|
+
return 'You have exceeded your API quota or rate limit. Wait before making more requests or upgrade your plan';
|
|
308
|
+
}
|
|
309
|
+
if (lowerMessage.includes('unauthorized') || lowerMessage.includes('api key')) {
|
|
310
|
+
return 'Check that your GEMINI_API_KEY is valid and has the necessary permissions';
|
|
311
|
+
}
|
|
312
|
+
if (lowerMessage.includes('forbidden')) {
|
|
313
|
+
return 'Your API key does not have permission for this operation';
|
|
314
|
+
}
|
|
315
|
+
return 'Check your API configuration and try again';
|
|
316
|
+
}
|
|
317
|
+
extractStatusCode(error) {
|
|
318
|
+
if (error && typeof error === 'object' && 'status' in error) {
|
|
319
|
+
return typeof error.status === 'number' ? error.status : undefined;
|
|
320
|
+
}
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Creates a new Gemini API client
|
|
326
|
+
* @param config Configuration containing API key and other settings
|
|
327
|
+
* @returns Result containing the client or an error
|
|
328
|
+
*/
|
|
329
|
+
export function createGeminiClient(config) {
|
|
330
|
+
try {
|
|
331
|
+
const genai = new GoogleGenAI({
|
|
332
|
+
apiKey: config.geminiApiKey,
|
|
333
|
+
});
|
|
334
|
+
return Ok(new GeminiClientImpl(genai, config.imageQuality));
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
338
|
+
return Err(new GeminiAPIError(`Failed to initialize Gemini client: ${errorMessage}`, 'Verify your GEMINI_API_KEY is valid and the @google/genai package is properly installed'));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=geminiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiClient.js","sourceRoot":"","sources":["../../src/api/geminiClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini Text Client for text generation
|
|
3
|
+
* Pure API client for interacting with Google AI Studio
|
|
4
|
+
* Handles text generation without any prompt optimization logic
|
|
5
|
+
*/
|
|
6
|
+
import type { Result } from '../types/result.js';
|
|
7
|
+
import type { Config } from '../utils/config.js';
|
|
8
|
+
import { GeminiAPIError, NetworkError } from '../utils/errors.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options for text generation
|
|
11
|
+
*/
|
|
12
|
+
export interface GenerationConfig {
|
|
13
|
+
temperature?: number;
|
|
14
|
+
maxTokens?: number;
|
|
15
|
+
timeout?: number;
|
|
16
|
+
systemInstruction?: string;
|
|
17
|
+
inputImage?: string;
|
|
18
|
+
topP?: number;
|
|
19
|
+
topK?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Interface for Gemini Text Client - pure API client
|
|
23
|
+
*/
|
|
24
|
+
export interface GeminiTextClient {
|
|
25
|
+
/**
|
|
26
|
+
* Generate text using Gemini API
|
|
27
|
+
* @param prompt The prompt to send to the API
|
|
28
|
+
* @param config Optional configuration for generation
|
|
29
|
+
* @returns Result containing generated text or error
|
|
30
|
+
*/
|
|
31
|
+
generateText(prompt: string, config?: GenerationConfig): Promise<Result<string, GeminiAPIError | NetworkError>>;
|
|
32
|
+
/**
|
|
33
|
+
* Validate connection to Gemini API
|
|
34
|
+
* @returns Result indicating if connection is successful
|
|
35
|
+
*/
|
|
36
|
+
validateConnection(): Promise<Result<boolean, GeminiAPIError | NetworkError>>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new Gemini Text Client for prompt generation
|
|
40
|
+
* @param config Configuration containing API key and settings
|
|
41
|
+
* @returns Result containing the client or an error
|
|
42
|
+
*/
|
|
43
|
+
export declare function createGeminiTextClient(config: Config): Result<GeminiTextClient, GeminiAPIError>;
|
|
44
|
+
//# sourceMappingURL=geminiTextClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiTextClient.d.ts","sourceRoot":"","sources":["../../src/api/geminiTextClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,YAAY,CACV,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC,CAAA;IAEzD;;;OAGG;IACH,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC,CAAA;CAC9E;AA+RD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAY/F"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini Text Client for text generation
|
|
3
|
+
* Pure API client for interacting with Google AI Studio
|
|
4
|
+
* Handles text generation without any prompt optimization logic
|
|
5
|
+
*/
|
|
6
|
+
import { GoogleGenAI } from '@google/genai';
|
|
7
|
+
import { Err, Ok } from '../types/result.js';
|
|
8
|
+
import { GeminiAPIError, NetworkError } from '../utils/errors.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default configuration for text generation
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_GENERATION_CONFIG = {
|
|
13
|
+
temperature: 0.7,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
timeout: 15000,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Implementation of Gemini Text Client - pure API client
|
|
19
|
+
*/
|
|
20
|
+
class GeminiTextClientImpl {
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.modelName = 'gemini-2.5-flash';
|
|
23
|
+
this.genai = new GoogleGenAI({
|
|
24
|
+
apiKey: config.geminiApiKey,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async generateText(prompt, config = {}) {
|
|
28
|
+
// Merge with default configuration
|
|
29
|
+
const mergedConfig = {
|
|
30
|
+
...DEFAULT_GENERATION_CONFIG,
|
|
31
|
+
...config,
|
|
32
|
+
};
|
|
33
|
+
// Validate input
|
|
34
|
+
const validationResult = this.validatePromptInput(prompt);
|
|
35
|
+
if (!validationResult.success) {
|
|
36
|
+
return validationResult;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
// Call Gemini API
|
|
40
|
+
const generatedText = await this.callGeminiAPI(prompt, mergedConfig);
|
|
41
|
+
return Ok(generatedText);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return this.handleError(error, 'text generation');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Call Gemini API to generate text
|
|
49
|
+
*/
|
|
50
|
+
async callGeminiAPI(prompt, config) {
|
|
51
|
+
try {
|
|
52
|
+
// Generate content with timeout
|
|
53
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
54
|
+
setTimeout(() => reject(new Error('API call timeout')), config.timeout || 15000);
|
|
55
|
+
});
|
|
56
|
+
// Build contents based on whether input image is provided (multimodal support)
|
|
57
|
+
let contents;
|
|
58
|
+
if (config.inputImage) {
|
|
59
|
+
// Multimodal request: combine image and text
|
|
60
|
+
contents = [
|
|
61
|
+
{
|
|
62
|
+
parts: [
|
|
63
|
+
{
|
|
64
|
+
inlineData: {
|
|
65
|
+
data: config.inputImage,
|
|
66
|
+
mimeType: 'image/jpeg', // Assuming JPEG for simplicity; can be enhanced later
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
text: prompt,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Text-only request
|
|
78
|
+
contents = prompt;
|
|
79
|
+
}
|
|
80
|
+
// Call Gemini API
|
|
81
|
+
const apiCall = this.genai.models.generateContent({
|
|
82
|
+
model: this.modelName,
|
|
83
|
+
contents,
|
|
84
|
+
config: {
|
|
85
|
+
...(config.systemInstruction !== undefined && {
|
|
86
|
+
systemInstruction: config.systemInstruction,
|
|
87
|
+
}),
|
|
88
|
+
temperature: config.temperature || 0.7,
|
|
89
|
+
maxOutputTokens: config.maxTokens || 8192,
|
|
90
|
+
topP: config.topP ?? 0.95,
|
|
91
|
+
topK: config.topK ?? 40,
|
|
92
|
+
thinkingConfig: {
|
|
93
|
+
thinkingBudget: 0,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
const response = await Promise.race([apiCall, timeoutPromise]);
|
|
98
|
+
// Extract text from response - handling both possible response structures
|
|
99
|
+
let responseText;
|
|
100
|
+
if (typeof response.text === 'string') {
|
|
101
|
+
responseText = response.text;
|
|
102
|
+
}
|
|
103
|
+
else if (response.response?.text && typeof response.response.text === 'function') {
|
|
104
|
+
responseText = response.response.text();
|
|
105
|
+
}
|
|
106
|
+
else if (response.response?.candidates?.[0]?.content?.parts?.[0]?.text) {
|
|
107
|
+
responseText = response.response.candidates[0].content.parts[0].text;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
throw new Error('Unable to extract text from API response');
|
|
111
|
+
}
|
|
112
|
+
if (!responseText || responseText.trim().length === 0) {
|
|
113
|
+
throw new Error('Empty response from Gemini API');
|
|
114
|
+
}
|
|
115
|
+
return responseText.trim();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// Re-throw with context for proper error handling
|
|
119
|
+
throw new Error(`Gemini API call failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async validateConnection() {
|
|
123
|
+
try {
|
|
124
|
+
// Validate by checking if the models object exists
|
|
125
|
+
if (!this.genai.models) {
|
|
126
|
+
return Err(new GeminiAPIError('Failed to access Gemini models', 'Check your GEMINI_API_KEY configuration'));
|
|
127
|
+
}
|
|
128
|
+
// API key validation happens during actual API calls
|
|
129
|
+
return Ok(true);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
return this.handleError(error, 'connection validation');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
handleError(error, context) {
|
|
136
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
137
|
+
// Check for network errors
|
|
138
|
+
if (this.isNetworkError(error)) {
|
|
139
|
+
return Err(new NetworkError(`Network error during ${context}: ${errorMessage}`, 'Check your internet connection and try again'));
|
|
140
|
+
}
|
|
141
|
+
// Check for API errors
|
|
142
|
+
if (this.isAPIError(error)) {
|
|
143
|
+
return Err(new GeminiAPIError(`Failed during ${context}: ${errorMessage}`, this.getAPIErrorSuggestion(errorMessage)));
|
|
144
|
+
}
|
|
145
|
+
// Generic error
|
|
146
|
+
return Err(new GeminiAPIError(`Failed during ${context}: ${errorMessage}`, 'Check your API configuration and try again'));
|
|
147
|
+
}
|
|
148
|
+
isNetworkError(error) {
|
|
149
|
+
if (error instanceof Error) {
|
|
150
|
+
const networkErrorCodes = ['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND'];
|
|
151
|
+
return networkErrorCodes.some((code) => error.message.includes(code) || error.code === code);
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
isAPIError(error) {
|
|
156
|
+
if (error instanceof Error) {
|
|
157
|
+
const apiErrorKeywords = ['quota', 'rate limit', 'unauthorized', 'forbidden', 'api key'];
|
|
158
|
+
return apiErrorKeywords.some((keyword) => error.message.toLowerCase().includes(keyword));
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
getAPIErrorSuggestion(errorMessage) {
|
|
163
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
164
|
+
if (lowerMessage.includes('quota') || lowerMessage.includes('rate limit')) {
|
|
165
|
+
return 'You have exceeded your API quota or rate limit. Wait before making more requests or upgrade your plan';
|
|
166
|
+
}
|
|
167
|
+
if (lowerMessage.includes('unauthorized') || lowerMessage.includes('api key')) {
|
|
168
|
+
return 'Check that your GEMINI_API_KEY is valid and has the necessary permissions';
|
|
169
|
+
}
|
|
170
|
+
if (lowerMessage.includes('forbidden')) {
|
|
171
|
+
return 'Your API key does not have permission for this operation';
|
|
172
|
+
}
|
|
173
|
+
return 'Check your API configuration and try again';
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Validate prompt input before processing
|
|
177
|
+
*/
|
|
178
|
+
validatePromptInput(prompt) {
|
|
179
|
+
if (!prompt || prompt.trim().length === 0) {
|
|
180
|
+
return Err(new GeminiAPIError('Empty prompt provided', 'Please provide a non-empty prompt for generation'));
|
|
181
|
+
}
|
|
182
|
+
if (prompt.length > 100000) {
|
|
183
|
+
return Err(new GeminiAPIError('Prompt too long', 'Please provide a shorter prompt (under 100,000 characters)'));
|
|
184
|
+
}
|
|
185
|
+
return Ok(true);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Creates a new Gemini Text Client for prompt generation
|
|
190
|
+
* @param config Configuration containing API key and settings
|
|
191
|
+
* @returns Result containing the client or an error
|
|
192
|
+
*/
|
|
193
|
+
export function createGeminiTextClient(config) {
|
|
194
|
+
try {
|
|
195
|
+
return Ok(new GeminiTextClientImpl(config));
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
199
|
+
return Err(new GeminiAPIError(`Failed to initialize Gemini Text client: ${errorMessage}`, 'Verify your GEMINI_API_KEY is valid and the @google/genai package is properly installed'));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=geminiTextClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiTextClient.js","sourceRoot":"","sources":["../../src/api/geminiTextClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Manager for handling image file operations
|
|
3
|
+
* Provides functionality for saving images and managing directories
|
|
4
|
+
*/
|
|
5
|
+
import type { Result } from '../types/result.js';
|
|
6
|
+
import { FileOperationError } from '../utils/errors.js';
|
|
7
|
+
/**
|
|
8
|
+
* Interface for file management operations
|
|
9
|
+
*/
|
|
10
|
+
export interface FileManager {
|
|
11
|
+
saveImage(imageData: Buffer, outputPath: string, format?: string): Promise<Result<string, FileOperationError>>;
|
|
12
|
+
ensureDirectoryExists(dirPath: string): Result<void, FileOperationError>;
|
|
13
|
+
generateFileName(): string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates a file manager for image file operations
|
|
17
|
+
* @returns FileManager implementation
|
|
18
|
+
*/
|
|
19
|
+
export declare function createFileManager(): FileManager;
|
|
20
|
+
//# sourceMappingURL=fileManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileManager.d.ts","sourceRoot":"","sources":["../../src/business/fileManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAcvD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,CACP,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAA;IAC9C,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;IACxE,gBAAgB,IAAI,MAAM,CAAA;CAC3B;AA+BD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAsC/C"}
|