@fre4x/gemini 1.0.54 → 1.0.57
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/dist/index.js +303 -319
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -46218,6 +46218,34 @@ function getApiKeyFromEnv() {
|
|
|
46218
46218
|
}
|
|
46219
46219
|
|
|
46220
46220
|
// ../packages/shared/dist/errors.js
|
|
46221
|
+
function createApiError(message, statusCode) {
|
|
46222
|
+
let hint = "Check your network connection and retry.";
|
|
46223
|
+
let type = "Service Error";
|
|
46224
|
+
if (statusCode === 429) {
|
|
46225
|
+
type = "Rate Limit";
|
|
46226
|
+
hint = "Request volume is too high. Suggestion: Wait briefly before retrying or reduce concurrent calls.";
|
|
46227
|
+
} else if (statusCode === 401 || statusCode === 403) {
|
|
46228
|
+
type = "Authentication Error";
|
|
46229
|
+
hint = "The request could not be authorized. Suggestion: Verify your API key or token in the environment configuration.";
|
|
46230
|
+
} else if (statusCode && statusCode >= 500) {
|
|
46231
|
+
type = "Upstream Error";
|
|
46232
|
+
hint = "The remote service is experiencing temporary issues. Suggestion: Try again in a few minutes.";
|
|
46233
|
+
} else if (statusCode === 404) {
|
|
46234
|
+
type = "Not Found";
|
|
46235
|
+
hint = "The requested information could not be found. Suggestion: Check if the ID, Ticker, or query parameters are correct.";
|
|
46236
|
+
}
|
|
46237
|
+
return {
|
|
46238
|
+
isError: true,
|
|
46239
|
+
content: [
|
|
46240
|
+
{
|
|
46241
|
+
type: "text",
|
|
46242
|
+
text: `${type}: ${message}
|
|
46243
|
+
|
|
46244
|
+
**Next Action**: ${hint}`
|
|
46245
|
+
}
|
|
46246
|
+
]
|
|
46247
|
+
};
|
|
46248
|
+
}
|
|
46221
46249
|
function createValidationError(field, message) {
|
|
46222
46250
|
return {
|
|
46223
46251
|
isError: true,
|
|
@@ -60261,7 +60289,8 @@ config(en_default());
|
|
|
60261
60289
|
var zod_default = external_exports;
|
|
60262
60290
|
|
|
60263
60291
|
// ../packages/shared/dist/pagination.js
|
|
60264
|
-
var
|
|
60292
|
+
var zodCompat = zod_exports;
|
|
60293
|
+
var z2 = zodCompat.z ?? zodCompat.default?.z ?? zodCompat.default ?? zodCompat;
|
|
60265
60294
|
var paginationSchema = z2.object({
|
|
60266
60295
|
limit: z2.number().int().min(1).max(100).default(20).describe("Maximum results to return (1\u2013100, default 20)"),
|
|
60267
60296
|
offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination (default 0)")
|
|
@@ -67486,11 +67515,12 @@ var StdioServerTransport = class {
|
|
|
67486
67515
|
};
|
|
67487
67516
|
|
|
67488
67517
|
// src/index.ts
|
|
67489
|
-
var
|
|
67518
|
+
var zodCompat2 = zod_exports;
|
|
67519
|
+
var z3 = zodCompat2.z ?? zodCompat2.default?.z ?? zodCompat2.default ?? zodCompat2;
|
|
67490
67520
|
var IS_MOCK = process.env.GEMINI_MOCK === "true" || process.env.MOCK === "true";
|
|
67491
67521
|
var PACKAGE_VERSION = getPackageVersion(import.meta.url);
|
|
67492
|
-
var DEFAULT_TEXT_MODEL = "gemini-2.
|
|
67493
|
-
var DEFAULT_IMAGE_MODEL = "imagen-
|
|
67522
|
+
var DEFAULT_TEXT_MODEL = "gemini-2.0-flash";
|
|
67523
|
+
var DEFAULT_IMAGE_MODEL = "imagen-3.0-generate-001";
|
|
67494
67524
|
var DEFAULT_VIDEO_MODEL = "veo-2.0-generate-001";
|
|
67495
67525
|
var ALLOWED_MEDIA_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
67496
67526
|
"image/png",
|
|
@@ -67523,9 +67553,7 @@ function getApiKey() {
|
|
|
67523
67553
|
}
|
|
67524
67554
|
function getAi() {
|
|
67525
67555
|
if (IS_MOCK) {
|
|
67526
|
-
throw new Error(
|
|
67527
|
-
"AI SDK not initialized. Ensure GEMINI_API_KEY is set and MOCK mode is off."
|
|
67528
|
-
);
|
|
67556
|
+
throw new Error("AI SDK not initialized in MOCK mode.");
|
|
67529
67557
|
}
|
|
67530
67558
|
if (!ai) {
|
|
67531
67559
|
ai = new GoogleGenAI({ apiKey: getApiKey() });
|
|
@@ -67550,6 +67578,19 @@ function withApiKey(videoUrl) {
|
|
|
67550
67578
|
return `${videoUrl}${separator}key=${encodeURIComponent(apiKey)}`;
|
|
67551
67579
|
}
|
|
67552
67580
|
}
|
|
67581
|
+
function getErrorMessage(error48) {
|
|
67582
|
+
return error48 instanceof Error ? error48.message : String(error48);
|
|
67583
|
+
}
|
|
67584
|
+
function withStatusCode(error48, statusCode) {
|
|
67585
|
+
return Object.assign(error48, { statusCode });
|
|
67586
|
+
}
|
|
67587
|
+
function isErrorWithStatusCode(error48) {
|
|
67588
|
+
if (!(error48 instanceof Error)) {
|
|
67589
|
+
return false;
|
|
67590
|
+
}
|
|
67591
|
+
const statusCode = Reflect.get(error48, "statusCode");
|
|
67592
|
+
return typeof statusCode === "number";
|
|
67593
|
+
}
|
|
67553
67594
|
var FILE_EXT_TO_MIME = {
|
|
67554
67595
|
".png": "image/png",
|
|
67555
67596
|
".jpg": "image/jpeg",
|
|
@@ -67568,127 +67609,91 @@ var FILE_EXT_TO_MIME = {
|
|
|
67568
67609
|
".mov": "video/quicktime",
|
|
67569
67610
|
".pdf": "application/pdf"
|
|
67570
67611
|
};
|
|
67612
|
+
var AnalyzeMediaOutputSchema = z3.object({
|
|
67613
|
+
analysis: z3.string(),
|
|
67614
|
+
source: z3.string(),
|
|
67615
|
+
mimeType: z3.string(),
|
|
67616
|
+
savedPath: z3.string().optional()
|
|
67617
|
+
});
|
|
67618
|
+
var ListModelsOutputSchema = z3.object({
|
|
67619
|
+
imageModels: z3.array(z3.string()),
|
|
67620
|
+
videoModels: z3.array(z3.string())
|
|
67621
|
+
});
|
|
67622
|
+
var GenerateImageOutputSchema = z3.object({
|
|
67623
|
+
images: z3.array(
|
|
67624
|
+
z3.object({
|
|
67625
|
+
data: z3.string(),
|
|
67626
|
+
mimeType: z3.string(),
|
|
67627
|
+
savedPath: z3.string().optional()
|
|
67628
|
+
})
|
|
67629
|
+
),
|
|
67630
|
+
prompt: z3.string()
|
|
67631
|
+
});
|
|
67632
|
+
var GenerateVideoOutputSchema = z3.object({
|
|
67633
|
+
operationName: z3.string(),
|
|
67634
|
+
prompt: z3.string(),
|
|
67635
|
+
status: z3.string()
|
|
67636
|
+
});
|
|
67637
|
+
var VideoStatusOutputSchema = z3.object({
|
|
67638
|
+
done: z3.boolean(),
|
|
67639
|
+
videos: z3.array(
|
|
67640
|
+
z3.object({
|
|
67641
|
+
url: z3.string(),
|
|
67642
|
+
savedPath: z3.string().optional()
|
|
67643
|
+
})
|
|
67644
|
+
),
|
|
67645
|
+
error: z3.string().optional()
|
|
67646
|
+
});
|
|
67571
67647
|
var ANALYZE_MEDIA_TOOL = {
|
|
67572
67648
|
name: "analyze_media",
|
|
67573
67649
|
description: "Analyze an image or audio file from a URL or file path.",
|
|
67574
|
-
inputSchema: {
|
|
67575
|
-
|
|
67576
|
-
|
|
67577
|
-
|
|
67578
|
-
|
|
67579
|
-
|
|
67580
|
-
|
|
67581
|
-
|
|
67582
|
-
|
|
67583
|
-
|
|
67584
|
-
minLength: 1,
|
|
67585
|
-
description: "URL, file:// path, or local file path."
|
|
67586
|
-
},
|
|
67587
|
-
mime_type: {
|
|
67588
|
-
type: "string",
|
|
67589
|
-
description: "Optional MIME type override."
|
|
67590
|
-
},
|
|
67591
|
-
model: {
|
|
67592
|
-
type: "string",
|
|
67593
|
-
default: DEFAULT_TEXT_MODEL,
|
|
67594
|
-
description: "Gemini model to use for analysis."
|
|
67595
|
-
},
|
|
67596
|
-
output_dir: {
|
|
67597
|
-
type: "string",
|
|
67598
|
-
description: "Optional directory to save the analysis result as a .txt file."
|
|
67599
|
-
}
|
|
67600
|
-
},
|
|
67601
|
-
required: ["media_source"]
|
|
67602
|
-
}
|
|
67650
|
+
inputSchema: z3.object({
|
|
67651
|
+
prompt: z3.string().min(1).default("Describe this media.").describe("Optional question or instruction for the media."),
|
|
67652
|
+
media_source: z3.string().min(1).describe("URL, file:// path, or local file path."),
|
|
67653
|
+
mime_type: z3.string().optional().describe("Optional MIME type override."),
|
|
67654
|
+
model: z3.string().optional().default(DEFAULT_TEXT_MODEL).describe("Gemini model to use for analysis."),
|
|
67655
|
+
output_dir: z3.string().optional().describe(
|
|
67656
|
+
"Optional directory to save the analysis result as a .txt file."
|
|
67657
|
+
)
|
|
67658
|
+
}).strict(),
|
|
67659
|
+
outputSchema: AnalyzeMediaOutputSchema
|
|
67603
67660
|
};
|
|
67604
67661
|
var LIST_MODELS_TOOL = {
|
|
67605
67662
|
name: "list_models",
|
|
67606
67663
|
description: "List available Gemini image and video models.",
|
|
67607
|
-
inputSchema: {
|
|
67608
|
-
|
|
67609
|
-
|
|
67610
|
-
|
|
67611
|
-
capability: {
|
|
67612
|
-
type: "string",
|
|
67613
|
-
description: "Filter by capability: image, video, or all.",
|
|
67614
|
-
enum: ["all", "image", "video"],
|
|
67615
|
-
default: "all"
|
|
67616
|
-
}
|
|
67617
|
-
},
|
|
67618
|
-
required: []
|
|
67619
|
-
}
|
|
67664
|
+
inputSchema: z3.object({
|
|
67665
|
+
capability: z3.enum(["all", "image", "video"]).default("all").describe("Filter by capability: image, video, or all.")
|
|
67666
|
+
}).strict(),
|
|
67667
|
+
outputSchema: ListModelsOutputSchema
|
|
67620
67668
|
};
|
|
67621
67669
|
var GENERATE_IMAGE_TOOL = {
|
|
67622
67670
|
name: "generate_image",
|
|
67623
67671
|
description: "Generate an image using Imagen and optionally save it to disk.",
|
|
67624
|
-
inputSchema: {
|
|
67625
|
-
|
|
67626
|
-
|
|
67627
|
-
|
|
67628
|
-
|
|
67629
|
-
|
|
67630
|
-
|
|
67631
|
-
description: "Description of the image to generate."
|
|
67632
|
-
},
|
|
67633
|
-
aspect_ratio: {
|
|
67634
|
-
type: "string",
|
|
67635
|
-
enum: ["1:1", "16:9", "9:16"],
|
|
67636
|
-
default: "1:1",
|
|
67637
|
-
description: "Aspect ratio for the image."
|
|
67638
|
-
},
|
|
67639
|
-
model: {
|
|
67640
|
-
type: "string",
|
|
67641
|
-
default: DEFAULT_IMAGE_MODEL,
|
|
67642
|
-
description: "Imagen model to use."
|
|
67643
|
-
},
|
|
67644
|
-
output_dir: {
|
|
67645
|
-
type: "string",
|
|
67646
|
-
description: "Directory to save the image file."
|
|
67647
|
-
}
|
|
67648
|
-
},
|
|
67649
|
-
required: ["prompt"]
|
|
67650
|
-
}
|
|
67672
|
+
inputSchema: z3.object({
|
|
67673
|
+
prompt: z3.string().min(1).describe("Description of the image to generate."),
|
|
67674
|
+
aspect_ratio: z3.enum(["1:1", "16:9", "9:16"]).default("1:1").describe("Aspect ratio for the image."),
|
|
67675
|
+
model: z3.string().default(DEFAULT_IMAGE_MODEL).describe("Imagen model to use."),
|
|
67676
|
+
output_dir: z3.string().optional().describe("Directory to save the image file.")
|
|
67677
|
+
}).strict(),
|
|
67678
|
+
outputSchema: GenerateImageOutputSchema
|
|
67651
67679
|
};
|
|
67652
67680
|
var GENERATE_VIDEO_TOOL = {
|
|
67653
67681
|
name: "generate_video",
|
|
67654
67682
|
description: "Start an async video generation request using Veo.",
|
|
67655
|
-
inputSchema: {
|
|
67656
|
-
|
|
67657
|
-
|
|
67658
|
-
|
|
67659
|
-
|
|
67660
|
-
type: "string",
|
|
67661
|
-
minLength: 1,
|
|
67662
|
-
description: "Description of the video to generate."
|
|
67663
|
-
},
|
|
67664
|
-
model: {
|
|
67665
|
-
type: "string",
|
|
67666
|
-
default: DEFAULT_VIDEO_MODEL,
|
|
67667
|
-
description: "Veo model to use."
|
|
67668
|
-
}
|
|
67669
|
-
},
|
|
67670
|
-
required: ["prompt"]
|
|
67671
|
-
}
|
|
67683
|
+
inputSchema: z3.object({
|
|
67684
|
+
prompt: z3.string().min(1).describe("Description of the video to generate."),
|
|
67685
|
+
model: z3.string().default(DEFAULT_VIDEO_MODEL).describe("Veo model to use.")
|
|
67686
|
+
}).strict(),
|
|
67687
|
+
outputSchema: GenerateVideoOutputSchema
|
|
67672
67688
|
};
|
|
67673
67689
|
var GET_VIDEO_STATUS_TOOL = {
|
|
67674
67690
|
name: "get_video_status",
|
|
67675
67691
|
description: "Check the status of a video generation request.",
|
|
67676
|
-
inputSchema: {
|
|
67677
|
-
|
|
67678
|
-
|
|
67679
|
-
|
|
67680
|
-
|
|
67681
|
-
type: "string",
|
|
67682
|
-
minLength: 1,
|
|
67683
|
-
description: "Operation name returned by generate_video."
|
|
67684
|
-
},
|
|
67685
|
-
output_dir: {
|
|
67686
|
-
type: "string",
|
|
67687
|
-
description: "Directory to save the completed video file."
|
|
67688
|
-
}
|
|
67689
|
-
},
|
|
67690
|
-
required: ["operation_name"]
|
|
67691
|
-
}
|
|
67692
|
+
inputSchema: z3.object({
|
|
67693
|
+
operation_name: z3.string().min(1).describe("Operation name returned by generate_video."),
|
|
67694
|
+
output_dir: z3.string().optional().describe("Directory to save the completed video file.")
|
|
67695
|
+
}).strict(),
|
|
67696
|
+
outputSchema: VideoStatusOutputSchema
|
|
67692
67697
|
};
|
|
67693
67698
|
var TOOL_DEFINITIONS = [
|
|
67694
67699
|
ANALYZE_MEDIA_TOOL,
|
|
@@ -67717,8 +67722,9 @@ async function resolveMediaSource(mediaSource, mimeTypeOverride) {
|
|
|
67717
67722
|
if (mediaSource.startsWith("http://") || mediaSource.startsWith("https://")) {
|
|
67718
67723
|
const response = await fetch(mediaSource);
|
|
67719
67724
|
if (!response.ok) {
|
|
67720
|
-
throw
|
|
67721
|
-
|
|
67725
|
+
throw withStatusCode(
|
|
67726
|
+
new Error("Failed to fetch media source."),
|
|
67727
|
+
response.status
|
|
67722
67728
|
);
|
|
67723
67729
|
}
|
|
67724
67730
|
const mimeType2 = mimeTypeOverride || response.headers.get("content-type")?.split(";")[0]?.trim() || inferredMimeType;
|
|
@@ -67754,54 +67760,25 @@ async function resolveMediaSource(mediaSource, mimeTypeOverride) {
|
|
|
67754
67760
|
label: mediaSource.startsWith("file://") ? mediaSource : `file://${filePath}`
|
|
67755
67761
|
};
|
|
67756
67762
|
}
|
|
67757
|
-
function
|
|
67758
|
-
return createValidationError(field, message);
|
|
67759
|
-
}
|
|
67760
|
-
function parseArgs(schema, args) {
|
|
67761
|
-
const parsed = schema.safeParse(args ?? {});
|
|
67762
|
-
if (!parsed.success) {
|
|
67763
|
-
const issue2 = parsed.error.issues[0];
|
|
67764
|
-
return {
|
|
67765
|
-
success: false,
|
|
67766
|
-
error: validationError(
|
|
67767
|
-
issue2?.path.length ? issue2.path.join(".") : "arguments",
|
|
67768
|
-
issue2?.message ?? parsed.error.message
|
|
67769
|
-
)
|
|
67770
|
-
};
|
|
67771
|
-
}
|
|
67772
|
-
return { success: true, data: parsed.data };
|
|
67773
|
-
}
|
|
67774
|
-
function textResult(text) {
|
|
67763
|
+
function textResult(text, structuredContent) {
|
|
67775
67764
|
return {
|
|
67776
|
-
content: [{ type: "text", text }]
|
|
67765
|
+
content: [{ type: "text", text }],
|
|
67766
|
+
structuredContent
|
|
67777
67767
|
};
|
|
67778
67768
|
}
|
|
67779
67769
|
function formatModelLines(models, title) {
|
|
67780
67770
|
return [title, ...models.map((model) => `- ${model}`), ""];
|
|
67781
67771
|
}
|
|
67782
|
-
async function analyzeMedia(
|
|
67783
|
-
const
|
|
67784
|
-
z3.object({
|
|
67785
|
-
prompt: z3.string().min(1).default("Describe this media."),
|
|
67786
|
-
media_source: z3.string().min(1),
|
|
67787
|
-
mime_type: z3.string().optional(),
|
|
67788
|
-
model: z3.string().optional().default(DEFAULT_TEXT_MODEL),
|
|
67789
|
-
output_dir: z3.string().optional()
|
|
67790
|
-
}).strict(),
|
|
67791
|
-
rawArgs
|
|
67792
|
-
);
|
|
67793
|
-
if (!parsed.success) {
|
|
67794
|
-
return parsed.error;
|
|
67795
|
-
}
|
|
67796
|
-
const { prompt, media_source, mime_type, model, output_dir } = parsed.data;
|
|
67772
|
+
async function analyzeMedia(args) {
|
|
67773
|
+
const { prompt, media_source, mime_type, model, output_dir } = args;
|
|
67797
67774
|
let media;
|
|
67798
67775
|
try {
|
|
67799
67776
|
media = await resolveMediaSource(media_source, mime_type);
|
|
67800
67777
|
} catch (error48) {
|
|
67801
|
-
|
|
67802
|
-
|
|
67803
|
-
|
|
67804
|
-
);
|
|
67778
|
+
if (isErrorWithStatusCode(error48)) {
|
|
67779
|
+
return createApiError(error48.message, error48.statusCode);
|
|
67780
|
+
}
|
|
67781
|
+
return createValidationError("media_source", getErrorMessage(error48));
|
|
67805
67782
|
}
|
|
67806
67783
|
let responseText;
|
|
67807
67784
|
if (IS_MOCK) {
|
|
@@ -67813,7 +67790,7 @@ Model: ${model}
|
|
|
67813
67790
|
Mock response \u2014 no API call made.`;
|
|
67814
67791
|
} else {
|
|
67815
67792
|
const response = await getAi().models.generateContent({
|
|
67816
|
-
model,
|
|
67793
|
+
model: model || DEFAULT_TEXT_MODEL,
|
|
67817
67794
|
contents: [
|
|
67818
67795
|
{
|
|
67819
67796
|
role: "user",
|
|
@@ -67831,68 +67808,70 @@ Mock response \u2014 no API call made.`;
|
|
|
67831
67808
|
});
|
|
67832
67809
|
responseText = response.text || "No analysis generated.";
|
|
67833
67810
|
}
|
|
67811
|
+
let savedPath;
|
|
67834
67812
|
if (output_dir) {
|
|
67835
67813
|
try {
|
|
67836
67814
|
const fname = `analysis-${Date.now()}.txt`;
|
|
67837
|
-
|
|
67815
|
+
savedPath = path2.join(output_dir, fname);
|
|
67838
67816
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67839
|
-
await fs3.writeFile(
|
|
67840
|
-
return textResult(
|
|
67841
|
-
`${responseText}
|
|
67842
|
-
|
|
67843
|
-
\u2705 Analysis result saved to: ${fpath}`
|
|
67844
|
-
);
|
|
67817
|
+
await fs3.writeFile(savedPath, responseText);
|
|
67845
67818
|
} catch (error48) {
|
|
67846
67819
|
return textResult(
|
|
67847
67820
|
`${responseText}
|
|
67848
67821
|
|
|
67849
|
-
\u26A0\uFE0F Failed to save analysis result: ${error48
|
|
67822
|
+
\u26A0\uFE0F Failed to save analysis result: ${getErrorMessage(error48)}`,
|
|
67823
|
+
{
|
|
67824
|
+
analysis: responseText,
|
|
67825
|
+
source: media.label,
|
|
67826
|
+
mimeType: media.mimeType
|
|
67827
|
+
}
|
|
67850
67828
|
);
|
|
67851
67829
|
}
|
|
67852
67830
|
}
|
|
67853
|
-
return textResult(
|
|
67854
|
-
}
|
|
67855
|
-
|
|
67856
|
-
|
|
67857
|
-
|
|
67858
|
-
|
|
67859
|
-
|
|
67860
|
-
|
|
67831
|
+
return textResult(
|
|
67832
|
+
savedPath ? `${responseText}
|
|
67833
|
+
|
|
67834
|
+
\u2705 Analysis result saved to: ${savedPath}` : responseText,
|
|
67835
|
+
{
|
|
67836
|
+
analysis: responseText,
|
|
67837
|
+
source: media.label,
|
|
67838
|
+
mimeType: media.mimeType,
|
|
67839
|
+
savedPath
|
|
67840
|
+
}
|
|
67861
67841
|
);
|
|
67862
|
-
|
|
67863
|
-
|
|
67864
|
-
}
|
|
67865
|
-
const { capability } = parsed.data;
|
|
67842
|
+
}
|
|
67843
|
+
async function listModels(args) {
|
|
67844
|
+
const { capability } = args;
|
|
67866
67845
|
if (IS_MOCK) {
|
|
67846
|
+
const imageModels2 = [
|
|
67847
|
+
DEFAULT_IMAGE_MODEL,
|
|
67848
|
+
"imagen-3.0-ultra-generate-001",
|
|
67849
|
+
"imagen-3.0-fast-generate-001"
|
|
67850
|
+
];
|
|
67851
|
+
const videoModels2 = [DEFAULT_VIDEO_MODEL];
|
|
67867
67852
|
const lines2 = ["## Available Gemini Models", ""];
|
|
67868
67853
|
if (capability === "all" || capability === "image") {
|
|
67869
67854
|
lines2.push(
|
|
67870
|
-
...formatModelLines(
|
|
67871
|
-
[
|
|
67872
|
-
`${DEFAULT_IMAGE_MODEL} \u2B50 (recommended default)`,
|
|
67873
|
-
"imagen-4.0-ultra-generate-001 (highest quality)",
|
|
67874
|
-
"imagen-4.0-fast-generate-001 (fastest)"
|
|
67875
|
-
],
|
|
67876
|
-
"### \u{1F5BC}\uFE0F Image Generation"
|
|
67877
|
-
)
|
|
67855
|
+
...formatModelLines(imageModels2, "### \u{1F5BC}\uFE0F Image Generation")
|
|
67878
67856
|
);
|
|
67879
67857
|
}
|
|
67880
67858
|
if (capability === "all" || capability === "video") {
|
|
67881
67859
|
lines2.push(
|
|
67882
|
-
...formatModelLines(
|
|
67883
|
-
[DEFAULT_VIDEO_MODEL],
|
|
67884
|
-
"### \u{1F3AC} Video Generation"
|
|
67885
|
-
)
|
|
67860
|
+
...formatModelLines(videoModels2, "### \u{1F3AC} Video Generation")
|
|
67886
67861
|
);
|
|
67887
67862
|
}
|
|
67888
|
-
return textResult(lines2.join("\n").trim()
|
|
67863
|
+
return textResult(lines2.join("\n").trim(), {
|
|
67864
|
+
imageModels: capability === "video" ? [] : imageModels2,
|
|
67865
|
+
videoModels: capability === "image" ? [] : videoModels2
|
|
67866
|
+
});
|
|
67889
67867
|
}
|
|
67890
67868
|
const resp = await fetch(
|
|
67891
67869
|
`https://generativelanguage.googleapis.com/v1beta/models?key=${getApiKey()}&pageSize=200`
|
|
67892
67870
|
);
|
|
67893
67871
|
if (!resp.ok) {
|
|
67894
|
-
|
|
67895
|
-
|
|
67872
|
+
return createApiError(
|
|
67873
|
+
"The model listing service is unavailable.",
|
|
67874
|
+
resp.status
|
|
67896
67875
|
);
|
|
67897
67876
|
}
|
|
67898
67877
|
const data = await resp.json();
|
|
@@ -67909,57 +67888,70 @@ async function listModels(rawArgs) {
|
|
|
67909
67888
|
if (capability === "all" || capability === "video") {
|
|
67910
67889
|
lines.push(...formatModelLines(videoModels, "### \u{1F3AC} Video Generation"));
|
|
67911
67890
|
}
|
|
67912
|
-
return textResult(lines.join("\n").trim() || "No models found."
|
|
67891
|
+
return textResult(lines.join("\n").trim() || "No models found.", {
|
|
67892
|
+
imageModels: capability === "video" ? [] : imageModels,
|
|
67893
|
+
videoModels: capability === "image" ? [] : videoModels
|
|
67894
|
+
});
|
|
67913
67895
|
}
|
|
67914
|
-
async function generateImage(
|
|
67915
|
-
const
|
|
67916
|
-
z3.object({
|
|
67917
|
-
prompt: z3.string().min(1),
|
|
67918
|
-
aspect_ratio: z3.enum(["1:1", "16:9", "9:16"]).default("1:1"),
|
|
67919
|
-
model: z3.string().default(DEFAULT_IMAGE_MODEL),
|
|
67920
|
-
output_dir: z3.string().optional()
|
|
67921
|
-
}).strict(),
|
|
67922
|
-
rawArgs
|
|
67923
|
-
);
|
|
67924
|
-
if (!parsed.success) {
|
|
67925
|
-
return parsed.error;
|
|
67926
|
-
}
|
|
67927
|
-
const { prompt, aspect_ratio, model, output_dir } = parsed.data;
|
|
67896
|
+
async function generateImage(args) {
|
|
67897
|
+
const { prompt, aspect_ratio, model, output_dir } = args;
|
|
67928
67898
|
if (IS_MOCK) {
|
|
67929
67899
|
const mockBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
|
|
67930
|
-
|
|
67931
|
-
{
|
|
67932
|
-
type: "text",
|
|
67933
|
-
text: `\u2705 Image generated successfully (1 image, prompt: "${prompt}").`
|
|
67934
|
-
},
|
|
67935
|
-
{ type: "image", data: mockBase64, mimeType: "image/png" }
|
|
67936
|
-
];
|
|
67900
|
+
let savedPath;
|
|
67937
67901
|
if (output_dir) {
|
|
67938
67902
|
try {
|
|
67939
67903
|
const fname = `image-${Date.now()}.png`;
|
|
67940
|
-
|
|
67904
|
+
savedPath = path2.join(output_dir, fname);
|
|
67941
67905
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67942
|
-
await fs3.writeFile(
|
|
67943
|
-
|
|
67944
|
-
|
|
67945
|
-
|
|
67946
|
-
});
|
|
67906
|
+
await fs3.writeFile(
|
|
67907
|
+
savedPath,
|
|
67908
|
+
Buffer.from(mockBase64, "base64")
|
|
67909
|
+
);
|
|
67947
67910
|
} catch (error48) {
|
|
67948
|
-
|
|
67949
|
-
|
|
67950
|
-
|
|
67951
|
-
|
|
67911
|
+
return {
|
|
67912
|
+
content: [
|
|
67913
|
+
{
|
|
67914
|
+
type: "text",
|
|
67915
|
+
text: `\u2705 Image generated successfully.
|
|
67916
|
+
|
|
67917
|
+
\u26A0\uFE0F Failed to save image: ${getErrorMessage(error48)}`
|
|
67918
|
+
},
|
|
67919
|
+
{
|
|
67920
|
+
type: "image",
|
|
67921
|
+
data: mockBase64,
|
|
67922
|
+
mimeType: "image/png"
|
|
67923
|
+
}
|
|
67924
|
+
],
|
|
67925
|
+
structuredContent: {
|
|
67926
|
+
images: [{ data: mockBase64, mimeType: "image/png" }],
|
|
67927
|
+
prompt
|
|
67928
|
+
}
|
|
67929
|
+
};
|
|
67952
67930
|
}
|
|
67953
67931
|
}
|
|
67954
|
-
return {
|
|
67932
|
+
return {
|
|
67933
|
+
content: [
|
|
67934
|
+
{
|
|
67935
|
+
type: "text",
|
|
67936
|
+
text: `\u2705 Image generated successfully.${savedPath ? `
|
|
67937
|
+
Saved to: ${savedPath}` : ""}`
|
|
67938
|
+
},
|
|
67939
|
+
{ type: "image", data: mockBase64, mimeType: "image/png" }
|
|
67940
|
+
],
|
|
67941
|
+
structuredContent: {
|
|
67942
|
+
images: [
|
|
67943
|
+
{ data: mockBase64, mimeType: "image/png", savedPath }
|
|
67944
|
+
],
|
|
67945
|
+
prompt
|
|
67946
|
+
}
|
|
67947
|
+
};
|
|
67955
67948
|
}
|
|
67956
67949
|
const response = await getAi().models.generateImages({
|
|
67957
|
-
model,
|
|
67950
|
+
model: model || DEFAULT_IMAGE_MODEL,
|
|
67958
67951
|
prompt,
|
|
67959
67952
|
config: { numberOfImages: 1, aspectRatio: aspect_ratio }
|
|
67960
67953
|
});
|
|
67961
67954
|
const images = (response.generatedImages ?? []).map((img) => ({
|
|
67962
|
-
type: "image",
|
|
67963
67955
|
data: img.image?.imageBytes ?? "",
|
|
67964
67956
|
mimeType: "image/png"
|
|
67965
67957
|
}));
|
|
@@ -67968,108 +67960,75 @@ async function generateImage(rawArgs) {
|
|
|
67968
67960
|
content: [
|
|
67969
67961
|
{
|
|
67970
67962
|
type: "text",
|
|
67971
|
-
text: `Image generation returned no results.
|
|
67972
|
-
- Content policy violation in prompt
|
|
67973
|
-
- Model unavailable (${model}) in your region/API tier
|
|
67974
|
-
- Prompt unsupported or aspect ratio invalid (${aspect_ratio})
|
|
67975
|
-
|
|
67976
|
-
Check Imagen access at https://ai.google.dev/`
|
|
67963
|
+
text: `Image generation returned no results. Check Imagen access and policies.`
|
|
67977
67964
|
}
|
|
67978
67965
|
],
|
|
67979
67966
|
isError: true
|
|
67980
67967
|
};
|
|
67981
67968
|
}
|
|
67982
|
-
const
|
|
67983
|
-
let saveErrorText = "";
|
|
67969
|
+
const savedImages = [];
|
|
67984
67970
|
if (output_dir) {
|
|
67985
67971
|
try {
|
|
67986
67972
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67987
|
-
const
|
|
67988
|
-
|
|
67989
|
-
|
|
67990
|
-
|
|
67991
|
-
|
|
67992
|
-
|
|
67993
|
-
})
|
|
67994
|
-
);
|
|
67995
|
-
savedPaths.push(...paths);
|
|
67973
|
+
for (const [index, img] of images.entries()) {
|
|
67974
|
+
const fname = `image-${Date.now()}-${index + 1}.png`;
|
|
67975
|
+
const fpath = path2.join(output_dir, fname);
|
|
67976
|
+
await fs3.writeFile(fpath, Buffer.from(img.data, "base64"));
|
|
67977
|
+
savedImages.push({ ...img, savedPath: fpath });
|
|
67978
|
+
}
|
|
67996
67979
|
} catch (error48) {
|
|
67997
|
-
|
|
67998
|
-
|
|
67999
|
-
\u26A0\uFE0F Failed to save images: ${error48.message}`;
|
|
67980
|
+
console.error(`Failed to save images: ${getErrorMessage(error48)}`);
|
|
67981
|
+
savedImages.push(...images);
|
|
68000
67982
|
}
|
|
67983
|
+
} else {
|
|
67984
|
+
savedImages.push(...images);
|
|
68001
67985
|
}
|
|
67986
|
+
const savedPaths = savedImages.map((img) => img.savedPath).filter(Boolean);
|
|
68002
67987
|
const content = [
|
|
68003
67988
|
{
|
|
68004
67989
|
type: "text",
|
|
68005
|
-
text: `\u2705 Image generated successfully
|
|
67990
|
+
text: `\u2705 Image generated successfully.${savedPaths.length > 0 ? `
|
|
68006
67991
|
Saved to:
|
|
68007
|
-
${savedPaths.join("\n")}` : ""}
|
|
67992
|
+
${savedPaths.join("\n")}` : ""}`
|
|
68008
67993
|
},
|
|
68009
|
-
...
|
|
67994
|
+
...savedImages.map((img) => ({
|
|
67995
|
+
type: "image",
|
|
67996
|
+
data: img.data,
|
|
67997
|
+
mimeType: img.mimeType
|
|
67998
|
+
}))
|
|
68010
67999
|
];
|
|
68011
|
-
return { content };
|
|
68000
|
+
return { content, structuredContent: { images: savedImages, prompt } };
|
|
68012
68001
|
}
|
|
68013
|
-
async function generateVideo(
|
|
68014
|
-
const
|
|
68015
|
-
z3.object({
|
|
68016
|
-
prompt: z3.string().min(1),
|
|
68017
|
-
model: z3.string().default(DEFAULT_VIDEO_MODEL)
|
|
68018
|
-
}).strict(),
|
|
68019
|
-
rawArgs
|
|
68020
|
-
);
|
|
68021
|
-
if (!parsed.success) {
|
|
68022
|
-
return parsed.error;
|
|
68023
|
-
}
|
|
68024
|
-
const { prompt, model } = parsed.data;
|
|
68002
|
+
async function generateVideo(args) {
|
|
68003
|
+
const { prompt, model } = args;
|
|
68025
68004
|
if (IS_MOCK) {
|
|
68026
|
-
|
|
68027
|
-
|
|
68028
|
-
|
|
68029
|
-
type: "text",
|
|
68030
|
-
text: `[Mock] Video generation started.
|
|
68031
|
-
Operation name: mock-operations/123456
|
|
68032
|
-
Model: ${model}
|
|
68005
|
+
const opName2 = "mock-operations/123456";
|
|
68006
|
+
return textResult(
|
|
68007
|
+
`[Mock] Video generation started.
|
|
68033
68008
|
|
|
68034
|
-
|
|
68035
|
-
|
|
68036
|
-
|
|
68037
|
-
|
|
68009
|
+
Operation name: ${opName2}
|
|
68010
|
+
|
|
68011
|
+
Call get_video_status to check progress.`,
|
|
68012
|
+
{ operationName: opName2, prompt, status: "queued" }
|
|
68013
|
+
);
|
|
68038
68014
|
}
|
|
68039
68015
|
const operation = await getAi().models.generateVideos({
|
|
68040
|
-
model,
|
|
68016
|
+
model: model || DEFAULT_VIDEO_MODEL,
|
|
68041
68017
|
prompt,
|
|
68042
68018
|
config: { numberOfVideos: 1 }
|
|
68043
68019
|
});
|
|
68044
68020
|
const opName = operation.name ?? "unknown";
|
|
68045
|
-
return
|
|
68046
|
-
|
|
68047
|
-
{
|
|
68048
|
-
type: "text",
|
|
68049
|
-
text: `Video generation started (async \u2014 typically takes 2\u20135 minutes).
|
|
68021
|
+
return textResult(
|
|
68022
|
+
`Video generation started.
|
|
68050
68023
|
|
|
68051
68024
|
Operation name: ${opName}
|
|
68052
68025
|
|
|
68053
|
-
Call get_video_status
|
|
68054
|
-
|
|
68055
|
-
|
|
68056
|
-
Poll every ~30 seconds until done=true.`
|
|
68057
|
-
}
|
|
68058
|
-
]
|
|
68059
|
-
};
|
|
68060
|
-
}
|
|
68061
|
-
async function getVideoStatus(rawArgs) {
|
|
68062
|
-
const parsed = parseArgs(
|
|
68063
|
-
z3.object({
|
|
68064
|
-
operation_name: z3.string().min(1),
|
|
68065
|
-
output_dir: z3.string().optional()
|
|
68066
|
-
}).strict(),
|
|
68067
|
-
rawArgs
|
|
68026
|
+
Call get_video_status every ~30s until complete.`,
|
|
68027
|
+
{ operationName: opName, prompt, status: "started" }
|
|
68068
68028
|
);
|
|
68069
|
-
|
|
68070
|
-
|
|
68071
|
-
}
|
|
68072
|
-
const { operation_name, output_dir } = parsed.data;
|
|
68029
|
+
}
|
|
68030
|
+
async function getVideoStatus(args) {
|
|
68031
|
+
const { operation_name, output_dir } = args;
|
|
68073
68032
|
let op;
|
|
68074
68033
|
if (IS_MOCK) {
|
|
68075
68034
|
op = {
|
|
@@ -68087,7 +68046,8 @@ async function getVideoStatus(rawArgs) {
|
|
|
68087
68046
|
}
|
|
68088
68047
|
if (!op.done) {
|
|
68089
68048
|
return textResult(
|
|
68090
|
-
`Operation ${operation_name} is still in progress. Check back in ~30 seconds
|
|
68049
|
+
`Operation ${operation_name} is still in progress. Check back in ~30 seconds.`,
|
|
68050
|
+
{ done: false, videos: [] }
|
|
68091
68051
|
);
|
|
68092
68052
|
}
|
|
68093
68053
|
if (op.error) {
|
|
@@ -68095,20 +68055,30 @@ async function getVideoStatus(rawArgs) {
|
|
|
68095
68055
|
content: [
|
|
68096
68056
|
{
|
|
68097
68057
|
type: "text",
|
|
68098
|
-
text: `Video generation failed: ${op.error.message
|
|
68058
|
+
text: `Video generation failed: ${op.error.message || "Unknown upstream error"}`
|
|
68099
68059
|
}
|
|
68100
68060
|
],
|
|
68061
|
+
structuredContent: {
|
|
68062
|
+
done: true,
|
|
68063
|
+
error: op.error.message,
|
|
68064
|
+
videos: []
|
|
68065
|
+
},
|
|
68101
68066
|
isError: true
|
|
68102
68067
|
};
|
|
68103
68068
|
}
|
|
68104
|
-
const videos = (op.response?.generatedVideos ?? []).map((
|
|
68069
|
+
const videos = (op.response?.generatedVideos ?? []).map((video) => video.video?.uri ?? "").filter(Boolean);
|
|
68105
68070
|
if (videos.length === 0) {
|
|
68106
|
-
return
|
|
68107
|
-
|
|
68108
|
-
|
|
68109
|
-
|
|
68071
|
+
return {
|
|
68072
|
+
content: [
|
|
68073
|
+
{
|
|
68074
|
+
type: "text",
|
|
68075
|
+
text: "Operation complete but no video URLs found."
|
|
68076
|
+
}
|
|
68077
|
+
],
|
|
68078
|
+
structuredContent: { done: true, videos: [] }
|
|
68079
|
+
};
|
|
68110
68080
|
}
|
|
68111
|
-
const
|
|
68081
|
+
const videoResults = [];
|
|
68112
68082
|
const videoContents = [];
|
|
68113
68083
|
await Promise.all(
|
|
68114
68084
|
videos.map(async (url2, index) => {
|
|
@@ -68118,9 +68088,7 @@ ${JSON.stringify(op.response, null, 2)}`
|
|
|
68118
68088
|
} else {
|
|
68119
68089
|
const videoResp = await fetch(withApiKey(url2));
|
|
68120
68090
|
if (!videoResp.ok) {
|
|
68121
|
-
throw new Error(
|
|
68122
|
-
`Failed to download video: ${videoResp.status}`
|
|
68123
|
-
);
|
|
68091
|
+
throw new Error(`Failed to download video.`);
|
|
68124
68092
|
}
|
|
68125
68093
|
const arrayBuffer = await videoResp.arrayBuffer();
|
|
68126
68094
|
buffer = Buffer.from(arrayBuffer);
|
|
@@ -68133,53 +68101,66 @@ ${JSON.stringify(op.response, null, 2)}`
|
|
|
68133
68101
|
blob: buffer.toString("base64")
|
|
68134
68102
|
}
|
|
68135
68103
|
});
|
|
68104
|
+
let savedPath;
|
|
68136
68105
|
if (output_dir) {
|
|
68137
68106
|
try {
|
|
68138
68107
|
const fname = `video-${Date.now()}-${index + 1}.mp4`;
|
|
68139
|
-
|
|
68108
|
+
savedPath = path2.join(output_dir, fname);
|
|
68140
68109
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
68141
|
-
await fs3.writeFile(
|
|
68142
|
-
savedPaths.push(fpath);
|
|
68110
|
+
await fs3.writeFile(savedPath, buffer);
|
|
68143
68111
|
} catch (error48) {
|
|
68144
|
-
console.error(
|
|
68112
|
+
console.error(
|
|
68113
|
+
`Failed to save video: ${getErrorMessage(error48)}`
|
|
68114
|
+
);
|
|
68145
68115
|
}
|
|
68146
68116
|
}
|
|
68117
|
+
videoResults.push({ url: url2, savedPath });
|
|
68147
68118
|
})
|
|
68148
68119
|
);
|
|
68149
|
-
const
|
|
68120
|
+
const savedPaths = videoResults.map((v) => v.savedPath).filter(Boolean);
|
|
68121
|
+
const summaryLines = [
|
|
68150
68122
|
`Video generation complete!
|
|
68151
68123
|
|
|
68152
68124
|
Download URLs:
|
|
68153
68125
|
${videos.join("\n")}`
|
|
68154
68126
|
];
|
|
68155
68127
|
if (savedPaths.length > 0) {
|
|
68156
|
-
|
|
68128
|
+
summaryLines.push(`
|
|
68129
|
+
|
|
68157
68130
|
Saved to:
|
|
68158
68131
|
${savedPaths.join("\n")}`);
|
|
68159
|
-
} else if (output_dir) {
|
|
68160
|
-
lines.push(`
|
|
68161
|
-
\u26A0\uFE0F Failed to save videos to disk.`);
|
|
68162
68132
|
}
|
|
68163
68133
|
return {
|
|
68164
68134
|
content: [
|
|
68165
|
-
{ type: "text", text:
|
|
68135
|
+
{ type: "text", text: summaryLines.join("") },
|
|
68166
68136
|
...videoContents
|
|
68167
|
-
]
|
|
68137
|
+
],
|
|
68138
|
+
structuredContent: { done: true, videos: videoResults }
|
|
68168
68139
|
};
|
|
68169
68140
|
}
|
|
68170
68141
|
async function handleToolCall(name, args) {
|
|
68171
68142
|
try {
|
|
68172
68143
|
switch (name) {
|
|
68173
68144
|
case "analyze_media":
|
|
68174
|
-
return await analyzeMedia(
|
|
68145
|
+
return await analyzeMedia(
|
|
68146
|
+
ANALYZE_MEDIA_TOOL.inputSchema.parse(args)
|
|
68147
|
+
);
|
|
68175
68148
|
case "list_models":
|
|
68176
|
-
return await listModels(
|
|
68149
|
+
return await listModels(
|
|
68150
|
+
LIST_MODELS_TOOL.inputSchema.parse(args)
|
|
68151
|
+
);
|
|
68177
68152
|
case "generate_image":
|
|
68178
|
-
return await generateImage(
|
|
68153
|
+
return await generateImage(
|
|
68154
|
+
GENERATE_IMAGE_TOOL.inputSchema.parse(args)
|
|
68155
|
+
);
|
|
68179
68156
|
case "generate_video":
|
|
68180
|
-
return await generateVideo(
|
|
68157
|
+
return await generateVideo(
|
|
68158
|
+
GENERATE_VIDEO_TOOL.inputSchema.parse(args)
|
|
68159
|
+
);
|
|
68181
68160
|
case "get_video_status":
|
|
68182
|
-
return await getVideoStatus(
|
|
68161
|
+
return await getVideoStatus(
|
|
68162
|
+
GET_VIDEO_STATUS_TOOL.inputSchema.parse(args)
|
|
68163
|
+
);
|
|
68183
68164
|
default:
|
|
68184
68165
|
throw new Error(`Tool not found: ${name}`);
|
|
68185
68166
|
}
|
|
@@ -68190,6 +68171,9 @@ async function handleToolCall(name, args) {
|
|
|
68190
68171
|
error48.issues[0]?.message || error48.message
|
|
68191
68172
|
);
|
|
68192
68173
|
}
|
|
68174
|
+
if (isErrorWithStatusCode(error48)) {
|
|
68175
|
+
return createApiError(error48.message, error48.statusCode);
|
|
68176
|
+
}
|
|
68193
68177
|
return createInternalError(error48);
|
|
68194
68178
|
}
|
|
68195
68179
|
}
|