@mixio-pro/kalaasetu-mcp 2.1.0 → 2.1.2-beta

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.
@@ -1,218 +0,0 @@
1
- import { z } from "zod";
2
- import * as fs from "fs";
3
- import * as path from "path";
4
- import { GoogleGenAI } from "@google/genai";
5
-
6
- async function wait(ms: number): Promise<void> {
7
- return new Promise((resolve) => setTimeout(resolve, ms));
8
- }
9
-
10
- function fileToBase64(filePath: string): { data: string; mimeType: string } {
11
- if (!fs.existsSync(filePath)) {
12
- throw new Error(`File not found: ${filePath}`);
13
- }
14
- const buf = fs.readFileSync(filePath);
15
- const data = Buffer.from(buf).toString("base64");
16
- // Detect mime type from extension
17
- const ext = path.extname(filePath).toLowerCase();
18
- const mimeType =
19
- ext === ".jpg" || ext === ".jpeg"
20
- ? "image/jpeg"
21
- : ext === ".png"
22
- ? "image/png"
23
- : ext === ".webp"
24
- ? "image/webp"
25
- : "image/png";
26
- return { data, mimeType };
27
- }
28
-
29
- export const imageToVideo = {
30
- name: "imageToVideo",
31
- description:
32
- "Generate videos from an image as starting first frame using Vertex Veo models (predictLongRunning + fetchPredictOperation).",
33
- parameters: z.object({
34
- prompt: z.string().describe("Text description for the video"),
35
- image_path: z
36
- .string()
37
- .optional()
38
- .describe("Path to source image for image-to-video generation"),
39
- aspect_ratio: z
40
- .string()
41
- .optional()
42
- .describe("Video aspect ratio: '16:9' or '9:16' (default: '9:16')"),
43
- duration_seconds: z
44
- .number()
45
- .optional()
46
- .describe("Video duration in seconds: 4, 6, or 8 (default: 6)"),
47
- resolution: z
48
- .string()
49
- .optional()
50
- .describe("Video resolution: '720p' or '1080p' (default: '720p')"),
51
- negative_prompt: z
52
- .string()
53
- .optional()
54
- .describe("Text describing what not to include in the video"),
55
- person_generation: z
56
- .string()
57
- .optional()
58
- .describe(
59
- "Controls generation of people: 'allow_adult' (default for image-to-video) or 'allow_all'"
60
- ),
61
- reference_images: z
62
- .array(z.string())
63
- .optional()
64
- .describe("Additional image paths for reference (max 3)"),
65
- output_path: z
66
- .string()
67
- .optional()
68
- .describe(
69
- "Output MP4 file path (if multiple predictions, index suffix is added)"
70
- ),
71
- gemini_api_key: z
72
- .string()
73
- .optional()
74
- .describe("Gemini API key (uses GEMINI_API_KEY env var if not provided)"),
75
- model_id: z
76
- .string()
77
- .optional()
78
- .describe("Model ID (default: veo-2.0-generate-001)"),
79
- }),
80
- execute: async (args: {
81
- prompt: string;
82
- image_path?: string;
83
- aspect_ratio?: string;
84
- duration_seconds?: number;
85
- resolution?: string;
86
- negative_prompt?: string;
87
- person_generation?: string;
88
- reference_images?: string[];
89
- output_path?: string;
90
- gemini_api_key?: string;
91
- model_id?: string;
92
- }) => {
93
- const apiKey = args.gemini_api_key || process.env.GEMINI_API_KEY;
94
- if (!apiKey) {
95
- throw new Error(
96
- "Gemini API key is required. Set GEMINI_API_KEY environment variable or pass gemini_api_key parameter. Get one at https://aistudio.google.com/app/apikey"
97
- );
98
- }
99
-
100
- const model = args.model_id || "veo-2.0-generate-001";
101
-
102
- // Initialize Google GenAI client
103
- const genai = new GoogleGenAI({ apiKey });
104
-
105
- // Build config for video generation
106
- const config: any = {};
107
-
108
- if (args.duration_seconds !== undefined) {
109
- config.duration_seconds = args.duration_seconds;
110
- } else {
111
- config.duration_seconds = 6; // default
112
- }
113
-
114
- if (args.aspect_ratio) {
115
- config.aspect_ratio = args.aspect_ratio;
116
- }
117
-
118
- try {
119
- // Start video generation operation
120
- console.error(`Starting video generation with model: ${model}`);
121
- let operation = await genai.models.generateVideos({
122
- model,
123
- prompt: args.prompt,
124
- config,
125
- });
126
-
127
- console.error("Operation started, waiting for completion...");
128
-
129
- // Poll until operation is complete (max 10 minutes)
130
- let tries = 0;
131
- const maxTries = 60; // 10 minutes with 10s intervals
132
-
133
- while (!operation.done && tries < maxTries) {
134
- await wait(10000); // Wait 10 seconds
135
- tries++;
136
- console.error(`Polling attempt ${tries}/${maxTries}...`);
137
-
138
- operation = await genai.operations.getVideosOperation({
139
- operation: operation,
140
- });
141
- }
142
-
143
- if (!operation.done) {
144
- throw new Error("Video generation timed out after 10 minutes");
145
- }
146
-
147
- console.error("Operation completed!");
148
- console.error(
149
- "Full Response:",
150
- JSON.stringify(operation.response, null, 2)
151
- );
152
-
153
- // Extract generated videos from response
154
- const generatedVideos = operation.response?.generatedVideos || [];
155
-
156
- if (!generatedVideos || generatedVideos.length === 0) {
157
- const respStr = JSON.stringify(operation.response, null, 2);
158
- return `Video generation completed but no videos found in response.\n\nFull Response:\n${respStr.slice(
159
- 0,
160
- 2000
161
- )}${respStr.length > 2000 ? "\n...(truncated)" : ""}`;
162
- }
163
-
164
- // Download and save videos
165
- const outputs: string[] = [];
166
-
167
- for (let i = 0; i < generatedVideos.length; i++) {
168
- const generatedVideo = generatedVideos[i];
169
- const videoUri = generatedVideo?.video?.uri;
170
-
171
- if (!videoUri) {
172
- console.warn(`Video ${i} has no URI`);
173
- continue;
174
- }
175
-
176
- console.error(
177
- `Downloading video ${i + 1}/${generatedVideos.length}...`
178
- );
179
-
180
- // Download video from URI
181
- const videoUrl = `${videoUri}&key=${apiKey}`;
182
- const response = await fetch(videoUrl);
183
-
184
- if (!response.ok) {
185
- throw new Error(
186
- `Failed to download video: ${response.status} ${response.statusText}`
187
- );
188
- }
189
-
190
- const buffer = await response.arrayBuffer();
191
-
192
- // Save video to file
193
- const filePath = args.output_path
194
- ? i === 0
195
- ? args.output_path
196
- : args.output_path.replace(/\.mp4$/i, `_${i}.mp4`)
197
- : `video_output_${Date.now()}${i === 0 ? "" : "_" + i}.mp4`;
198
- const absPath = path.resolve(filePath);
199
-
200
- fs.writeFileSync(absPath, Buffer.from(buffer));
201
- outputs.push(absPath);
202
- console.error(`Saved video to: ${absPath}`);
203
- }
204
-
205
- if (outputs.length > 0) {
206
- return `Video(s) saved successfully:\n${outputs
207
- .map((p, i) => `${i + 1}. ${p}`)
208
- .join("\n")}`;
209
- }
210
-
211
- return "Video generation completed but no videos were saved.";
212
- } catch (error: any) {
213
- throw new Error(
214
- `Video generation failed: ${error.message || JSON.stringify(error)}`
215
- );
216
- }
217
- },
218
- };