@mixio-pro/kalaasetu-mcp 2.0.11-beta → 2.1.1-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.
- package/package.json +6 -2
- package/src/index.ts +4 -3
- package/src/storage/index.ts +4 -3
- package/src/tools/fal/config.ts +9 -8
- package/src/tools/fal/dynamic-tools.ts +214 -237
- package/src/tools/fal/models.ts +115 -93
- package/src/tools/fal/storage.ts +66 -61
- package/src/tools/gemini.ts +302 -281
- package/src/tools/get-status.ts +50 -46
- package/src/tools/image-to-video.ts +309 -300
- package/src/tools/perplexity.ts +188 -172
- package/src/tools/youtube.ts +45 -41
- package/src/utils/llm-prompt-enhancer.ts +3 -2
- package/src/utils/logger.ts +71 -0
- package/src/utils/openmeter.ts +123 -0
- package/src/utils/prompt-enhancer-presets.ts +7 -5
- package/src/utils/remote-sync.ts +19 -10
- package/src/utils/tool-credits.ts +104 -0
- package/src/utils/tool-wrapper.ts +37 -6
- package/src/utils/url-file.ts +4 -3
- package/src/test-context.ts +0 -52
- package/src/test-error-handling.ts +0 -31
- package/src/tools/image-to-video.sdk-backup.ts +0 -218
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
* Each preset becomes a first-class MCP tool with its own Zod schema.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
8
|
+
import { z, type ZodTypeAny } from "zod";
|
|
9
|
+
import { safeToolExecute } from "../../utils/tool-wrapper";
|
|
10
10
|
import { resolveEnhancer } from "../../utils/prompt-enhancer-presets";
|
|
11
11
|
import { sanitizeResponse } from "../../utils/sanitize";
|
|
12
|
-
import { safeToolExecute } from "../../utils/tool-wrapper";
|
|
13
12
|
import {
|
|
14
|
-
AUTHENTICATED_TIMEOUT,
|
|
15
13
|
FAL_QUEUE_URL,
|
|
14
|
+
AUTHENTICATED_TIMEOUT,
|
|
16
15
|
getApiKey,
|
|
17
16
|
loadFalConfig,
|
|
18
17
|
type FalPresetConfig,
|
|
@@ -31,7 +30,7 @@ async function wait(ms: number): Promise<void> {
|
|
|
31
30
|
async function authenticatedRequest(
|
|
32
31
|
url: string,
|
|
33
32
|
method: "GET" | "POST" | "PUT" = "GET",
|
|
34
|
-
jsonData?: Record<string, any
|
|
33
|
+
jsonData?: Record<string, any>,
|
|
35
34
|
): Promise<any> {
|
|
36
35
|
const headers: Record<string, string> = {
|
|
37
36
|
Authorization: `Key ${getApiKey()}`,
|
|
@@ -68,10 +67,10 @@ async function authenticatedRequest(
|
|
|
68
67
|
* Sanitize parameters by removing null/undefined values.
|
|
69
68
|
*/
|
|
70
69
|
function sanitizeParameters(
|
|
71
|
-
parameters: Record<string, any
|
|
70
|
+
parameters: Record<string, any>,
|
|
72
71
|
): Record<string, any> {
|
|
73
72
|
return Object.fromEntries(
|
|
74
|
-
Object.entries(parameters).filter(([_, v]) => v != null)
|
|
73
|
+
Object.entries(parameters).filter(([_, v]) => v != null),
|
|
75
74
|
);
|
|
76
75
|
}
|
|
77
76
|
|
|
@@ -84,7 +83,7 @@ interface ProgressContext {
|
|
|
84
83
|
total: number;
|
|
85
84
|
}) => Promise<void>;
|
|
86
85
|
streamContent?: (
|
|
87
|
-
content: { type: "text"; text: string } | { type: "text"; text: string }[]
|
|
86
|
+
content: { type: "text"; text: string } | { type: "text"; text: string }[],
|
|
88
87
|
) => Promise<void>;
|
|
89
88
|
log?: {
|
|
90
89
|
info: (message: string, data?: any) => void;
|
|
@@ -92,13 +91,12 @@ interface ProgressContext {
|
|
|
92
91
|
};
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
|
|
96
94
|
/**
|
|
97
95
|
* Build a Zod object schema from preset input_schema using built-in z.fromJSONSchema.
|
|
98
96
|
*/
|
|
99
97
|
function buildZodSchema(
|
|
100
98
|
inputSchema: Record<string, any> | undefined,
|
|
101
|
-
defaultParams?: Record<string, any
|
|
99
|
+
defaultParams?: Record<string, any>,
|
|
102
100
|
): z.ZodObject<any> {
|
|
103
101
|
// Construct a properties object for JSON schema
|
|
104
102
|
const properties: Record<string, any> = {};
|
|
@@ -129,13 +127,13 @@ function buildZodSchema(
|
|
|
129
127
|
.optional()
|
|
130
128
|
.describe(
|
|
131
129
|
"If provided, resume polling for an existing request instead of starting a new one. " +
|
|
132
|
-
"Use the 'resume_endpoint' returned in an 'IN_PROGRESS' response."
|
|
130
|
+
"Use the 'resume_endpoint' returned in an 'IN_PROGRESS' response.",
|
|
133
131
|
),
|
|
134
132
|
auto_enhance: z
|
|
135
133
|
.boolean()
|
|
136
134
|
.default(true) // Our custom default
|
|
137
135
|
.describe(
|
|
138
|
-
"Whether to automatically enhance the prompt. Set to false to disable."
|
|
136
|
+
"Whether to automatically enhance the prompt. Set to false to disable.",
|
|
139
137
|
),
|
|
140
138
|
});
|
|
141
139
|
|
|
@@ -148,7 +146,7 @@ function buildZodSchema(
|
|
|
148
146
|
export function createToolFromPreset(preset: FalPresetConfig) {
|
|
149
147
|
const zodSchema = buildZodSchema(
|
|
150
148
|
preset.input_schema as Record<string, any>,
|
|
151
|
-
preset.defaultParams
|
|
149
|
+
preset.defaultParams,
|
|
152
150
|
);
|
|
153
151
|
|
|
154
152
|
const toolName = preset.presetName.startsWith("fal_")
|
|
@@ -164,266 +162,245 @@ export function createToolFromPreset(preset: FalPresetConfig) {
|
|
|
164
162
|
parameters: zodSchema,
|
|
165
163
|
timeoutMs: 90000, // 90 seconds MCP timeout
|
|
166
164
|
|
|
167
|
-
execute: async (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
} else {
|
|
198
|
-
// New request - start generation
|
|
199
|
-
try {
|
|
200
|
-
const apiKey = getApiKey();
|
|
201
|
-
if (context?.streamContent) {
|
|
202
|
-
await context.streamContent({
|
|
203
|
-
type: "text" as const,
|
|
204
|
-
text: `[FAL] ✓ API key found (${apiKey.slice(0, 8)}...). Using model: ${preset.modelId}`,
|
|
205
|
-
});
|
|
165
|
+
execute: async (args: Record<string, any>, context?: ProgressContext) => {
|
|
166
|
+
return safeToolExecute(
|
|
167
|
+
async () => {
|
|
168
|
+
let statusUrl: string;
|
|
169
|
+
let responseUrl: string;
|
|
170
|
+
let requestId: string;
|
|
171
|
+
|
|
172
|
+
// Handle resume flow
|
|
173
|
+
if (args.resume_endpoint) {
|
|
174
|
+
if (args.resume_endpoint.startsWith("http")) {
|
|
175
|
+
statusUrl = args.resume_endpoint;
|
|
176
|
+
responseUrl = args.resume_endpoint.replace(/\/status$/, "");
|
|
177
|
+
const urlParts = args.resume_endpoint.split("/");
|
|
178
|
+
const lastPart = urlParts[urlParts.length - 1] || "";
|
|
179
|
+
requestId =
|
|
180
|
+
lastPart.replace("/status", "") ||
|
|
181
|
+
urlParts[urlParts.length - 2] ||
|
|
182
|
+
"unknown";
|
|
183
|
+
context?.log?.info(
|
|
184
|
+
`Resuming with FAL URL: ${args.resume_endpoint}`,
|
|
185
|
+
);
|
|
186
|
+
} else {
|
|
187
|
+
// Legacy UUID format - reconstruct URL
|
|
188
|
+
requestId = args.resume_endpoint;
|
|
189
|
+
statusUrl = `${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}/status`;
|
|
190
|
+
responseUrl = `${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}`;
|
|
191
|
+
context?.log?.info(
|
|
192
|
+
`Resuming polling for ${preset.modelId} request: ${requestId}`,
|
|
193
|
+
);
|
|
206
194
|
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const schemaDefaults: Record<string, any> = {};
|
|
217
|
-
if (preset.input_schema) {
|
|
218
|
-
for (const [key, paramSchema] of Object.entries(preset.input_schema)) {
|
|
219
|
-
if ((paramSchema as any).default !== undefined) {
|
|
220
|
-
schemaDefaults[key] = (paramSchema as any).default;
|
|
195
|
+
} else {
|
|
196
|
+
// New request - start generation
|
|
197
|
+
try {
|
|
198
|
+
const apiKey = getApiKey();
|
|
199
|
+
if (context?.streamContent) {
|
|
200
|
+
await context.streamContent({
|
|
201
|
+
type: "text" as const,
|
|
202
|
+
text: `[FAL] ✓ API key found (${apiKey.slice(0, 8)}...). Using model: ${preset.modelId}`,
|
|
203
|
+
});
|
|
221
204
|
}
|
|
205
|
+
} catch (keyError: any) {
|
|
206
|
+
throw keyError;
|
|
222
207
|
}
|
|
223
|
-
}
|
|
224
208
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
...
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const expression = jsonata(preset.transformers.jsonata);
|
|
238
|
-
const transformed = await expression.evaluate(mergedParams);
|
|
239
|
-
if (transformed && typeof transformed === "object") {
|
|
240
|
-
Object.assign(mergedParams, transformed);
|
|
209
|
+
// Build parameters: input_schema defaults → defaultParams → user args
|
|
210
|
+
// Extract only the model parameters (exclude our internal fields)
|
|
211
|
+
const { resume_endpoint, auto_enhance, ...userParams } = args;
|
|
212
|
+
|
|
213
|
+
// Start with defaults from input_schema
|
|
214
|
+
const schemaDefaults: Record<string, any> = {};
|
|
215
|
+
if (preset.input_schema) {
|
|
216
|
+
for (const [key, paramSchema] of Object.entries(
|
|
217
|
+
preset.input_schema,
|
|
218
|
+
)) {
|
|
219
|
+
if ((paramSchema as any).default !== undefined) {
|
|
220
|
+
schemaDefaults[key] = (paramSchema as any).default;
|
|
241
221
|
}
|
|
242
|
-
} catch (err) {
|
|
243
|
-
context?.log?.info(`JSONata transformation failed: ${err}`);
|
|
244
222
|
}
|
|
245
223
|
}
|
|
246
224
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
225
|
+
// Merge: schema defaults → preset defaultParams → user params
|
|
226
|
+
const mergedParams = {
|
|
227
|
+
...schemaDefaults,
|
|
228
|
+
...(preset.defaultParams || {}),
|
|
229
|
+
...userParams,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Apply prompt enhancement if enabled
|
|
233
|
+
const shouldEnhance = auto_enhance !== false;
|
|
234
|
+
if (shouldEnhance && preset.promptEnhancer && mergedParams.prompt) {
|
|
235
|
+
const enhancerName =
|
|
236
|
+
typeof preset.promptEnhancer === "string"
|
|
237
|
+
? preset.promptEnhancer
|
|
238
|
+
: null;
|
|
239
|
+
|
|
240
|
+
if (enhancerName === "ltx2") {
|
|
241
|
+
const { enhancePromptWithLLM, isLLMEnhancerAvailable } =
|
|
242
|
+
await import("../../utils/llm-prompt-enhancer");
|
|
243
|
+
if (isLLMEnhancerAvailable()) {
|
|
244
|
+
try {
|
|
245
|
+
const originalPrompt = mergedParams.prompt;
|
|
246
|
+
mergedParams.prompt = await enhancePromptWithLLM(
|
|
247
|
+
mergedParams.prompt,
|
|
248
|
+
"ltx2",
|
|
249
|
+
);
|
|
250
|
+
context?.log?.info(
|
|
251
|
+
`LLM-enhanced prompt: "${originalPrompt}" → "${mergedParams.prompt}"`,
|
|
252
|
+
);
|
|
253
|
+
} catch (err) {
|
|
254
|
+
context?.log?.info(
|
|
255
|
+
`LLM enhancement failed, using original prompt`,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else if (preset.promptEnhancer) {
|
|
260
|
+
const enhancer = resolveEnhancer(preset.promptEnhancer);
|
|
261
|
+
if (enhancer.hasTransformations()) {
|
|
262
|
+
mergedParams.prompt = enhancer.enhance(mergedParams.prompt);
|
|
263
|
+
const negatives = enhancer.getNegativeElements();
|
|
264
|
+
if (negatives && !mergedParams.negative_prompt) {
|
|
265
|
+
mergedParams.negative_prompt = negatives;
|
|
257
266
|
}
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
269
|
}
|
|
261
|
-
}
|
|
262
270
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
:
|
|
270
|
-
|
|
271
|
-
if (enhancerName === "ltx2") {
|
|
272
|
-
const { enhancePromptWithLLM, isLLMEnhancerAvailable } =
|
|
273
|
-
await import("../../utils/llm-prompt-enhancer");
|
|
274
|
-
if (isLLMEnhancerAvailable()) {
|
|
275
|
-
try {
|
|
276
|
-
const originalPrompt = mergedParams.prompt;
|
|
277
|
-
mergedParams.prompt = await enhancePromptWithLLM(
|
|
278
|
-
mergedParams.prompt,
|
|
279
|
-
"ltx2"
|
|
280
|
-
);
|
|
281
|
-
context?.log?.info(
|
|
282
|
-
`LLM-enhanced prompt: "${originalPrompt}" → "${mergedParams.prompt}"`
|
|
283
|
-
);
|
|
284
|
-
} catch (err) {
|
|
285
|
-
context?.log?.info(
|
|
286
|
-
`LLM enhancement failed, using original prompt`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
} else if (preset.promptEnhancer) {
|
|
291
|
-
const enhancer = resolveEnhancer(preset.promptEnhancer);
|
|
292
|
-
if (enhancer.hasTransformations()) {
|
|
293
|
-
mergedParams.prompt = enhancer.enhance(mergedParams.prompt);
|
|
294
|
-
const negatives = enhancer.getNegativeElements();
|
|
295
|
-
if (negatives && !mergedParams.negative_prompt) {
|
|
296
|
-
mergedParams.negative_prompt = negatives;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
271
|
+
const sanitizedParams = sanitizeParameters(mergedParams);
|
|
272
|
+
const url = `${FAL_QUEUE_URL}/${preset.modelId}`;
|
|
273
|
+
|
|
274
|
+
if (context?.streamContent) {
|
|
275
|
+
await context.streamContent({
|
|
276
|
+
type: "text" as const,
|
|
277
|
+
text: `[FAL] Submitting generation request to ${preset.modelId}...`,
|
|
278
|
+
});
|
|
299
279
|
}
|
|
300
|
-
}
|
|
301
280
|
|
|
302
|
-
|
|
303
|
-
|
|
281
|
+
const queueRes = await authenticatedRequest(
|
|
282
|
+
url,
|
|
283
|
+
"POST",
|
|
284
|
+
sanitizedParams,
|
|
285
|
+
);
|
|
304
286
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
text: `[FAL] Submitting generation request to ${preset.modelId}...`,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
287
|
+
if (!queueRes.request_id && !queueRes.status_url) {
|
|
288
|
+
return JSON.stringify(sanitizeResponse(queueRes));
|
|
289
|
+
}
|
|
311
290
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
);
|
|
291
|
+
requestId =
|
|
292
|
+
queueRes.request_id ||
|
|
293
|
+
queueRes.status_url?.split("/").pop() ||
|
|
294
|
+
"";
|
|
317
295
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
296
|
+
if (!requestId) {
|
|
297
|
+
throw new Error("Could not extract request ID from response");
|
|
298
|
+
}
|
|
321
299
|
|
|
322
|
-
|
|
323
|
-
|
|
300
|
+
statusUrl =
|
|
301
|
+
queueRes.status_url ||
|
|
302
|
+
`${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}/status`;
|
|
303
|
+
responseUrl =
|
|
304
|
+
queueRes.response_url ||
|
|
305
|
+
`${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}`;
|
|
324
306
|
|
|
325
|
-
|
|
326
|
-
|
|
307
|
+
if (context?.streamContent) {
|
|
308
|
+
await context.streamContent({
|
|
309
|
+
type: "text" as const,
|
|
310
|
+
text: `[FAL] Generation started. resume_endpoint: ${statusUrl}`,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
327
313
|
}
|
|
328
314
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
`${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}/status`;
|
|
332
|
-
responseUrl =
|
|
333
|
-
queueRes.response_url ||
|
|
334
|
-
`${FAL_QUEUE_URL}/${preset.modelId}/requests/${requestId}`;
|
|
335
|
-
|
|
336
|
-
if (context?.streamContent) {
|
|
315
|
+
// Stream message for resume calls
|
|
316
|
+
if (args.resume_endpoint && context?.streamContent) {
|
|
337
317
|
await context.streamContent({
|
|
338
318
|
type: "text" as const,
|
|
339
|
-
text: `[FAL]
|
|
319
|
+
text: `[FAL] Resuming status check for job: ${requestId}`,
|
|
340
320
|
});
|
|
341
321
|
}
|
|
342
|
-
}
|
|
343
322
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
context?.log?.info(
|
|
366
|
-
`Status check 405 on ${statusUrl}, trying fallback...`
|
|
367
|
-
);
|
|
368
|
-
res = await authenticatedRequest(responseUrl, "GET");
|
|
369
|
-
statusUrl = responseUrl;
|
|
370
|
-
} else {
|
|
371
|
-
throw e;
|
|
323
|
+
// Poll for completion
|
|
324
|
+
const startTime = Date.now();
|
|
325
|
+
const MAX_POLL_TIME = 60000; // 60 seconds internal timeout
|
|
326
|
+
let pollCount = 0;
|
|
327
|
+
const POLL_INTERVAL = 3000;
|
|
328
|
+
|
|
329
|
+
while (Date.now() - startTime < MAX_POLL_TIME) {
|
|
330
|
+
pollCount++;
|
|
331
|
+
let res;
|
|
332
|
+
try {
|
|
333
|
+
res = await authenticatedRequest(statusUrl, "GET");
|
|
334
|
+
} catch (e: any) {
|
|
335
|
+
if (`${e}`.includes("405")) {
|
|
336
|
+
context?.log?.info(
|
|
337
|
+
`Status check 405 on ${statusUrl}, trying fallback...`,
|
|
338
|
+
);
|
|
339
|
+
res = await authenticatedRequest(responseUrl, "GET");
|
|
340
|
+
statusUrl = responseUrl;
|
|
341
|
+
} else {
|
|
342
|
+
throw e;
|
|
343
|
+
}
|
|
372
344
|
}
|
|
373
|
-
}
|
|
374
345
|
|
|
375
|
-
|
|
376
|
-
|
|
346
|
+
if (res.status_url) statusUrl = res.status_url;
|
|
347
|
+
if (res.response_url) responseUrl = res.response_url;
|
|
377
348
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
349
|
+
if (context?.reportProgress) {
|
|
350
|
+
const elapsed = Date.now() - startTime;
|
|
351
|
+
const progressPercent = Math.min(
|
|
352
|
+
Math.round((elapsed / MAX_POLL_TIME) * 100),
|
|
353
|
+
99,
|
|
354
|
+
);
|
|
355
|
+
await context.reportProgress({
|
|
356
|
+
progress: progressPercent,
|
|
357
|
+
total: 100,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
389
360
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
361
|
+
if (context?.streamContent && pollCount % 5 === 0) {
|
|
362
|
+
await context.streamContent({
|
|
363
|
+
type: "text" as const,
|
|
364
|
+
text: `[FAL] Still processing... (${Math.round(
|
|
365
|
+
(Date.now() - startTime) / 1000,
|
|
366
|
+
)}s elapsed, status: ${res.status})`,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
398
369
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
370
|
+
if (res.status === "COMPLETED") {
|
|
371
|
+
if (context?.reportProgress) {
|
|
372
|
+
await context.reportProgress({ progress: 100, total: 100 });
|
|
373
|
+
}
|
|
374
|
+
const finalResult = await authenticatedRequest(
|
|
375
|
+
responseUrl,
|
|
376
|
+
"GET",
|
|
377
|
+
);
|
|
378
|
+
return JSON.stringify(sanitizeResponse(finalResult));
|
|
402
379
|
}
|
|
403
|
-
const finalResult = await authenticatedRequest(responseUrl, "GET");
|
|
404
|
-
return JSON.stringify(sanitizeResponse(finalResult));
|
|
405
|
-
}
|
|
406
380
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
381
|
+
if (res.status === "FAILED") {
|
|
382
|
+
throw new Error(
|
|
383
|
+
`Generation failed: ${JSON.stringify(res.error || res)}`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
await wait(POLL_INTERVAL);
|
|
411
388
|
}
|
|
412
389
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
|
|
390
|
+
// Timeout - return resume_endpoint
|
|
391
|
+
return JSON.stringify({
|
|
392
|
+
status: "IN_PROGRESS",
|
|
393
|
+
request_id: requestId,
|
|
394
|
+
resume_endpoint: statusUrl,
|
|
395
|
+
status_url: statusUrl,
|
|
396
|
+
response_url: responseUrl,
|
|
397
|
+
message:
|
|
398
|
+
"The generation is still in progress. Call this tool again with resume_endpoint to continue polling.",
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
preset.presetName,
|
|
402
|
+
{ toolName: toolName },
|
|
403
|
+
);
|
|
427
404
|
},
|
|
428
405
|
};
|
|
429
406
|
}
|