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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +454 -0
  3. package/bin/install-skills.js +115 -0
  4. package/dist/api/geminiClient.d.ts +57 -0
  5. package/dist/api/geminiClient.d.ts.map +1 -0
  6. package/dist/api/geminiClient.js +341 -0
  7. package/dist/api/geminiClient.js.map +1 -0
  8. package/dist/api/geminiTextClient.d.ts +44 -0
  9. package/dist/api/geminiTextClient.d.ts.map +1 -0
  10. package/dist/api/geminiTextClient.js +202 -0
  11. package/dist/api/geminiTextClient.js.map +1 -0
  12. package/dist/business/fileManager.d.ts +20 -0
  13. package/dist/business/fileManager.d.ts.map +1 -0
  14. package/dist/business/fileManager.js +76 -0
  15. package/dist/business/fileManager.js.map +1 -0
  16. package/dist/business/inputValidator.d.ts +44 -0
  17. package/dist/business/inputValidator.d.ts.map +1 -0
  18. package/dist/business/inputValidator.js +213 -0
  19. package/dist/business/inputValidator.js.map +1 -0
  20. package/dist/business/responseBuilder.d.ts +21 -0
  21. package/dist/business/responseBuilder.d.ts.map +1 -0
  22. package/dist/business/responseBuilder.js +166 -0
  23. package/dist/business/responseBuilder.js.map +1 -0
  24. package/dist/business/structuredPromptGenerator.d.ts +56 -0
  25. package/dist/business/structuredPromptGenerator.d.ts.map +1 -0
  26. package/dist/business/structuredPromptGenerator.js +218 -0
  27. package/dist/business/structuredPromptGenerator.js.map +1 -0
  28. package/dist/index.d.ts +12 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +30 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/server/errorHandler.d.ts +29 -0
  33. package/dist/server/errorHandler.d.ts.map +1 -0
  34. package/dist/server/errorHandler.js +99 -0
  35. package/dist/server/errorHandler.js.map +1 -0
  36. package/dist/server/mcpServer.d.ts +159 -0
  37. package/dist/server/mcpServer.d.ts.map +1 -0
  38. package/dist/server/mcpServer.js +434 -0
  39. package/dist/server/mcpServer.js.map +1 -0
  40. package/dist/server-main.d.ts +5 -0
  41. package/dist/server-main.d.ts.map +1 -0
  42. package/dist/server-main.js +37 -0
  43. package/dist/server-main.js.map +1 -0
  44. package/dist/types/mcp.d.ts +121 -0
  45. package/dist/types/mcp.d.ts.map +1 -0
  46. package/dist/types/mcp.js +22 -0
  47. package/dist/types/mcp.js.map +1 -0
  48. package/dist/types/result.d.ts +27 -0
  49. package/dist/types/result.d.ts.map +1 -0
  50. package/dist/types/result.js +27 -0
  51. package/dist/types/result.js.map +1 -0
  52. package/dist/utils/config.d.ts +29 -0
  53. package/dist/utils/config.d.ts.map +1 -0
  54. package/dist/utils/config.js +56 -0
  55. package/dist/utils/config.js.map +1 -0
  56. package/dist/utils/errors.d.ts +84 -0
  57. package/dist/utils/errors.d.ts.map +1 -0
  58. package/dist/utils/errors.js +215 -0
  59. package/dist/utils/errors.js.map +1 -0
  60. package/dist/utils/logger.d.ts +80 -0
  61. package/dist/utils/logger.d.ts.map +1 -0
  62. package/dist/utils/logger.js +186 -0
  63. package/dist/utils/logger.js.map +1 -0
  64. package/dist/utils/security.d.ts +50 -0
  65. package/dist/utils/security.d.ts.map +1 -0
  66. package/dist/utils/security.js +116 -0
  67. package/dist/utils/security.js.map +1 -0
  68. package/package.json +89 -0
  69. 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"}