@fre4x/gemini 1.0.55 → 1.0.58
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 +296 -317
- 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() });
|
|
@@ -67553,6 +67581,16 @@ function withApiKey(videoUrl) {
|
|
|
67553
67581
|
function getErrorMessage(error48) {
|
|
67554
67582
|
return error48 instanceof Error ? error48.message : String(error48);
|
|
67555
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
|
+
}
|
|
67556
67594
|
var FILE_EXT_TO_MIME = {
|
|
67557
67595
|
".png": "image/png",
|
|
67558
67596
|
".jpg": "image/jpeg",
|
|
@@ -67571,127 +67609,91 @@ var FILE_EXT_TO_MIME = {
|
|
|
67571
67609
|
".mov": "video/quicktime",
|
|
67572
67610
|
".pdf": "application/pdf"
|
|
67573
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
|
+
});
|
|
67574
67647
|
var ANALYZE_MEDIA_TOOL = {
|
|
67575
67648
|
name: "analyze_media",
|
|
67576
67649
|
description: "Analyze an image or audio file from a URL or file path.",
|
|
67577
|
-
inputSchema: {
|
|
67578
|
-
|
|
67579
|
-
|
|
67580
|
-
|
|
67581
|
-
|
|
67582
|
-
|
|
67583
|
-
|
|
67584
|
-
|
|
67585
|
-
|
|
67586
|
-
|
|
67587
|
-
minLength: 1,
|
|
67588
|
-
description: "URL, file:// path, or local file path."
|
|
67589
|
-
},
|
|
67590
|
-
mime_type: {
|
|
67591
|
-
type: "string",
|
|
67592
|
-
description: "Optional MIME type override."
|
|
67593
|
-
},
|
|
67594
|
-
model: {
|
|
67595
|
-
type: "string",
|
|
67596
|
-
default: DEFAULT_TEXT_MODEL,
|
|
67597
|
-
description: "Gemini model to use for analysis."
|
|
67598
|
-
},
|
|
67599
|
-
output_dir: {
|
|
67600
|
-
type: "string",
|
|
67601
|
-
description: "Optional directory to save the analysis result as a .txt file."
|
|
67602
|
-
}
|
|
67603
|
-
},
|
|
67604
|
-
required: ["media_source"]
|
|
67605
|
-
}
|
|
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
|
|
67606
67660
|
};
|
|
67607
67661
|
var LIST_MODELS_TOOL = {
|
|
67608
67662
|
name: "list_models",
|
|
67609
67663
|
description: "List available Gemini image and video models.",
|
|
67610
|
-
inputSchema: {
|
|
67611
|
-
|
|
67612
|
-
|
|
67613
|
-
|
|
67614
|
-
capability: {
|
|
67615
|
-
type: "string",
|
|
67616
|
-
description: "Filter by capability: image, video, or all.",
|
|
67617
|
-
enum: ["all", "image", "video"],
|
|
67618
|
-
default: "all"
|
|
67619
|
-
}
|
|
67620
|
-
},
|
|
67621
|
-
required: []
|
|
67622
|
-
}
|
|
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
|
|
67623
67668
|
};
|
|
67624
67669
|
var GENERATE_IMAGE_TOOL = {
|
|
67625
67670
|
name: "generate_image",
|
|
67626
67671
|
description: "Generate an image using Imagen and optionally save it to disk.",
|
|
67627
|
-
inputSchema: {
|
|
67628
|
-
|
|
67629
|
-
|
|
67630
|
-
|
|
67631
|
-
|
|
67632
|
-
|
|
67633
|
-
|
|
67634
|
-
description: "Description of the image to generate."
|
|
67635
|
-
},
|
|
67636
|
-
aspect_ratio: {
|
|
67637
|
-
type: "string",
|
|
67638
|
-
enum: ["1:1", "16:9", "9:16"],
|
|
67639
|
-
default: "1:1",
|
|
67640
|
-
description: "Aspect ratio for the image."
|
|
67641
|
-
},
|
|
67642
|
-
model: {
|
|
67643
|
-
type: "string",
|
|
67644
|
-
default: DEFAULT_IMAGE_MODEL,
|
|
67645
|
-
description: "Imagen model to use."
|
|
67646
|
-
},
|
|
67647
|
-
output_dir: {
|
|
67648
|
-
type: "string",
|
|
67649
|
-
description: "Directory to save the image file."
|
|
67650
|
-
}
|
|
67651
|
-
},
|
|
67652
|
-
required: ["prompt"]
|
|
67653
|
-
}
|
|
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
|
|
67654
67679
|
};
|
|
67655
67680
|
var GENERATE_VIDEO_TOOL = {
|
|
67656
67681
|
name: "generate_video",
|
|
67657
67682
|
description: "Start an async video generation request using Veo.",
|
|
67658
|
-
inputSchema: {
|
|
67659
|
-
|
|
67660
|
-
|
|
67661
|
-
|
|
67662
|
-
|
|
67663
|
-
type: "string",
|
|
67664
|
-
minLength: 1,
|
|
67665
|
-
description: "Description of the video to generate."
|
|
67666
|
-
},
|
|
67667
|
-
model: {
|
|
67668
|
-
type: "string",
|
|
67669
|
-
default: DEFAULT_VIDEO_MODEL,
|
|
67670
|
-
description: "Veo model to use."
|
|
67671
|
-
}
|
|
67672
|
-
},
|
|
67673
|
-
required: ["prompt"]
|
|
67674
|
-
}
|
|
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
|
|
67675
67688
|
};
|
|
67676
67689
|
var GET_VIDEO_STATUS_TOOL = {
|
|
67677
67690
|
name: "get_video_status",
|
|
67678
67691
|
description: "Check the status of a video generation request.",
|
|
67679
|
-
inputSchema: {
|
|
67680
|
-
|
|
67681
|
-
|
|
67682
|
-
|
|
67683
|
-
|
|
67684
|
-
type: "string",
|
|
67685
|
-
minLength: 1,
|
|
67686
|
-
description: "Operation name returned by generate_video."
|
|
67687
|
-
},
|
|
67688
|
-
output_dir: {
|
|
67689
|
-
type: "string",
|
|
67690
|
-
description: "Directory to save the completed video file."
|
|
67691
|
-
}
|
|
67692
|
-
},
|
|
67693
|
-
required: ["operation_name"]
|
|
67694
|
-
}
|
|
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
|
|
67695
67697
|
};
|
|
67696
67698
|
var TOOL_DEFINITIONS = [
|
|
67697
67699
|
ANALYZE_MEDIA_TOOL,
|
|
@@ -67720,8 +67722,9 @@ async function resolveMediaSource(mediaSource, mimeTypeOverride) {
|
|
|
67720
67722
|
if (mediaSource.startsWith("http://") || mediaSource.startsWith("https://")) {
|
|
67721
67723
|
const response = await fetch(mediaSource);
|
|
67722
67724
|
if (!response.ok) {
|
|
67723
|
-
throw
|
|
67724
|
-
|
|
67725
|
+
throw withStatusCode(
|
|
67726
|
+
new Error("Failed to fetch media source."),
|
|
67727
|
+
response.status
|
|
67725
67728
|
);
|
|
67726
67729
|
}
|
|
67727
67730
|
const mimeType2 = mimeTypeOverride || response.headers.get("content-type")?.split(";")[0]?.trim() || inferredMimeType;
|
|
@@ -67757,54 +67760,25 @@ async function resolveMediaSource(mediaSource, mimeTypeOverride) {
|
|
|
67757
67760
|
label: mediaSource.startsWith("file://") ? mediaSource : `file://${filePath}`
|
|
67758
67761
|
};
|
|
67759
67762
|
}
|
|
67760
|
-
function
|
|
67761
|
-
return createValidationError(field, message);
|
|
67762
|
-
}
|
|
67763
|
-
function parseArgs(schema, args) {
|
|
67764
|
-
const parsed = schema.safeParse(args ?? {});
|
|
67765
|
-
if (!parsed.success) {
|
|
67766
|
-
const issue2 = parsed.error.issues[0];
|
|
67767
|
-
return {
|
|
67768
|
-
success: false,
|
|
67769
|
-
error: validationError(
|
|
67770
|
-
issue2?.path.length ? issue2.path.join(".") : "arguments",
|
|
67771
|
-
issue2?.message ?? parsed.error.message
|
|
67772
|
-
)
|
|
67773
|
-
};
|
|
67774
|
-
}
|
|
67775
|
-
return { success: true, data: parsed.data };
|
|
67776
|
-
}
|
|
67777
|
-
function textResult(text) {
|
|
67763
|
+
function textResult(text, structuredContent) {
|
|
67778
67764
|
return {
|
|
67779
|
-
content: [{ type: "text", text }]
|
|
67765
|
+
content: [{ type: "text", text }],
|
|
67766
|
+
structuredContent
|
|
67780
67767
|
};
|
|
67781
67768
|
}
|
|
67782
67769
|
function formatModelLines(models, title) {
|
|
67783
67770
|
return [title, ...models.map((model) => `- ${model}`), ""];
|
|
67784
67771
|
}
|
|
67785
|
-
async function analyzeMedia(
|
|
67786
|
-
const
|
|
67787
|
-
z3.object({
|
|
67788
|
-
prompt: z3.string().min(1).default("Describe this media."),
|
|
67789
|
-
media_source: z3.string().min(1),
|
|
67790
|
-
mime_type: z3.string().optional(),
|
|
67791
|
-
model: z3.string().optional().default(DEFAULT_TEXT_MODEL),
|
|
67792
|
-
output_dir: z3.string().optional()
|
|
67793
|
-
}).strict(),
|
|
67794
|
-
rawArgs
|
|
67795
|
-
);
|
|
67796
|
-
if (!parsed.success) {
|
|
67797
|
-
return parsed.error;
|
|
67798
|
-
}
|
|
67799
|
-
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;
|
|
67800
67774
|
let media;
|
|
67801
67775
|
try {
|
|
67802
67776
|
media = await resolveMediaSource(media_source, mime_type);
|
|
67803
67777
|
} catch (error48) {
|
|
67804
|
-
|
|
67805
|
-
|
|
67806
|
-
|
|
67807
|
-
);
|
|
67778
|
+
if (isErrorWithStatusCode(error48)) {
|
|
67779
|
+
return createApiError(error48.message, error48.statusCode);
|
|
67780
|
+
}
|
|
67781
|
+
return createValidationError("media_source", getErrorMessage(error48));
|
|
67808
67782
|
}
|
|
67809
67783
|
let responseText;
|
|
67810
67784
|
if (IS_MOCK) {
|
|
@@ -67816,7 +67790,7 @@ Model: ${model}
|
|
|
67816
67790
|
Mock response \u2014 no API call made.`;
|
|
67817
67791
|
} else {
|
|
67818
67792
|
const response = await getAi().models.generateContent({
|
|
67819
|
-
model,
|
|
67793
|
+
model: model || DEFAULT_TEXT_MODEL,
|
|
67820
67794
|
contents: [
|
|
67821
67795
|
{
|
|
67822
67796
|
role: "user",
|
|
@@ -67834,68 +67808,70 @@ Mock response \u2014 no API call made.`;
|
|
|
67834
67808
|
});
|
|
67835
67809
|
responseText = response.text || "No analysis generated.";
|
|
67836
67810
|
}
|
|
67811
|
+
let savedPath;
|
|
67837
67812
|
if (output_dir) {
|
|
67838
67813
|
try {
|
|
67839
67814
|
const fname = `analysis-${Date.now()}.txt`;
|
|
67840
|
-
|
|
67815
|
+
savedPath = path2.join(output_dir, fname);
|
|
67841
67816
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67842
|
-
await fs3.writeFile(
|
|
67843
|
-
return textResult(
|
|
67844
|
-
`${responseText}
|
|
67845
|
-
|
|
67846
|
-
\u2705 Analysis result saved to: ${fpath}`
|
|
67847
|
-
);
|
|
67817
|
+
await fs3.writeFile(savedPath, responseText);
|
|
67848
67818
|
} catch (error48) {
|
|
67849
67819
|
return textResult(
|
|
67850
67820
|
`${responseText}
|
|
67851
67821
|
|
|
67852
|
-
\u26A0\uFE0F Failed to save analysis result: ${getErrorMessage(error48)}
|
|
67822
|
+
\u26A0\uFE0F Failed to save analysis result: ${getErrorMessage(error48)}`,
|
|
67823
|
+
{
|
|
67824
|
+
analysis: responseText,
|
|
67825
|
+
source: media.label,
|
|
67826
|
+
mimeType: media.mimeType
|
|
67827
|
+
}
|
|
67853
67828
|
);
|
|
67854
67829
|
}
|
|
67855
67830
|
}
|
|
67856
|
-
return textResult(
|
|
67857
|
-
}
|
|
67858
|
-
|
|
67859
|
-
|
|
67860
|
-
|
|
67861
|
-
|
|
67862
|
-
|
|
67863
|
-
|
|
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
|
+
}
|
|
67864
67841
|
);
|
|
67865
|
-
|
|
67866
|
-
|
|
67867
|
-
}
|
|
67868
|
-
const { capability } = parsed.data;
|
|
67842
|
+
}
|
|
67843
|
+
async function listModels(args) {
|
|
67844
|
+
const { capability } = args;
|
|
67869
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];
|
|
67870
67852
|
const lines2 = ["## Available Gemini Models", ""];
|
|
67871
67853
|
if (capability === "all" || capability === "image") {
|
|
67872
67854
|
lines2.push(
|
|
67873
|
-
...formatModelLines(
|
|
67874
|
-
[
|
|
67875
|
-
`${DEFAULT_IMAGE_MODEL} \u2B50 (recommended default)`,
|
|
67876
|
-
"imagen-4.0-ultra-generate-001 (highest quality)",
|
|
67877
|
-
"imagen-4.0-fast-generate-001 (fastest)"
|
|
67878
|
-
],
|
|
67879
|
-
"### \u{1F5BC}\uFE0F Image Generation"
|
|
67880
|
-
)
|
|
67855
|
+
...formatModelLines(imageModels2, "### \u{1F5BC}\uFE0F Image Generation")
|
|
67881
67856
|
);
|
|
67882
67857
|
}
|
|
67883
67858
|
if (capability === "all" || capability === "video") {
|
|
67884
67859
|
lines2.push(
|
|
67885
|
-
...formatModelLines(
|
|
67886
|
-
[DEFAULT_VIDEO_MODEL],
|
|
67887
|
-
"### \u{1F3AC} Video Generation"
|
|
67888
|
-
)
|
|
67860
|
+
...formatModelLines(videoModels2, "### \u{1F3AC} Video Generation")
|
|
67889
67861
|
);
|
|
67890
67862
|
}
|
|
67891
|
-
return textResult(lines2.join("\n").trim()
|
|
67863
|
+
return textResult(lines2.join("\n").trim(), {
|
|
67864
|
+
imageModels: capability === "video" ? [] : imageModels2,
|
|
67865
|
+
videoModels: capability === "image" ? [] : videoModels2
|
|
67866
|
+
});
|
|
67892
67867
|
}
|
|
67893
67868
|
const resp = await fetch(
|
|
67894
67869
|
`https://generativelanguage.googleapis.com/v1beta/models?key=${getApiKey()}&pageSize=200`
|
|
67895
67870
|
);
|
|
67896
67871
|
if (!resp.ok) {
|
|
67897
|
-
|
|
67898
|
-
|
|
67872
|
+
return createApiError(
|
|
67873
|
+
"The model listing service is unavailable.",
|
|
67874
|
+
resp.status
|
|
67899
67875
|
);
|
|
67900
67876
|
}
|
|
67901
67877
|
const data = await resp.json();
|
|
@@ -67912,57 +67888,70 @@ async function listModels(rawArgs) {
|
|
|
67912
67888
|
if (capability === "all" || capability === "video") {
|
|
67913
67889
|
lines.push(...formatModelLines(videoModels, "### \u{1F3AC} Video Generation"));
|
|
67914
67890
|
}
|
|
67915
|
-
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
|
+
});
|
|
67916
67895
|
}
|
|
67917
|
-
async function generateImage(
|
|
67918
|
-
const
|
|
67919
|
-
z3.object({
|
|
67920
|
-
prompt: z3.string().min(1),
|
|
67921
|
-
aspect_ratio: z3.enum(["1:1", "16:9", "9:16"]).default("1:1"),
|
|
67922
|
-
model: z3.string().default(DEFAULT_IMAGE_MODEL),
|
|
67923
|
-
output_dir: z3.string().optional()
|
|
67924
|
-
}).strict(),
|
|
67925
|
-
rawArgs
|
|
67926
|
-
);
|
|
67927
|
-
if (!parsed.success) {
|
|
67928
|
-
return parsed.error;
|
|
67929
|
-
}
|
|
67930
|
-
const { prompt, aspect_ratio, model, output_dir } = parsed.data;
|
|
67896
|
+
async function generateImage(args) {
|
|
67897
|
+
const { prompt, aspect_ratio, model, output_dir } = args;
|
|
67931
67898
|
if (IS_MOCK) {
|
|
67932
67899
|
const mockBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
|
|
67933
|
-
|
|
67934
|
-
{
|
|
67935
|
-
type: "text",
|
|
67936
|
-
text: `\u2705 Image generated successfully (1 image, prompt: "${prompt}").`
|
|
67937
|
-
},
|
|
67938
|
-
{ type: "image", data: mockBase64, mimeType: "image/png" }
|
|
67939
|
-
];
|
|
67900
|
+
let savedPath;
|
|
67940
67901
|
if (output_dir) {
|
|
67941
67902
|
try {
|
|
67942
67903
|
const fname = `image-${Date.now()}.png`;
|
|
67943
|
-
|
|
67904
|
+
savedPath = path2.join(output_dir, fname);
|
|
67944
67905
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67945
|
-
await fs3.writeFile(
|
|
67946
|
-
|
|
67947
|
-
|
|
67948
|
-
|
|
67949
|
-
});
|
|
67906
|
+
await fs3.writeFile(
|
|
67907
|
+
savedPath,
|
|
67908
|
+
Buffer.from(mockBase64, "base64")
|
|
67909
|
+
);
|
|
67950
67910
|
} catch (error48) {
|
|
67951
|
-
|
|
67952
|
-
|
|
67953
|
-
|
|
67954
|
-
|
|
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
|
+
};
|
|
67955
67930
|
}
|
|
67956
67931
|
}
|
|
67957
|
-
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
|
+
};
|
|
67958
67948
|
}
|
|
67959
67949
|
const response = await getAi().models.generateImages({
|
|
67960
|
-
model,
|
|
67950
|
+
model: model || DEFAULT_IMAGE_MODEL,
|
|
67961
67951
|
prompt,
|
|
67962
67952
|
config: { numberOfImages: 1, aspectRatio: aspect_ratio }
|
|
67963
67953
|
});
|
|
67964
67954
|
const images = (response.generatedImages ?? []).map((img) => ({
|
|
67965
|
-
type: "image",
|
|
67966
67955
|
data: img.image?.imageBytes ?? "",
|
|
67967
67956
|
mimeType: "image/png"
|
|
67968
67957
|
}));
|
|
@@ -67971,108 +67960,75 @@ async function generateImage(rawArgs) {
|
|
|
67971
67960
|
content: [
|
|
67972
67961
|
{
|
|
67973
67962
|
type: "text",
|
|
67974
|
-
text: `Image generation returned no results.
|
|
67975
|
-
- Content policy violation in prompt
|
|
67976
|
-
- Model unavailable (${model}) in your region/API tier
|
|
67977
|
-
- Prompt unsupported or aspect ratio invalid (${aspect_ratio})
|
|
67978
|
-
|
|
67979
|
-
Check Imagen access at https://ai.google.dev/`
|
|
67963
|
+
text: `Image generation returned no results. Check Imagen access and policies.`
|
|
67980
67964
|
}
|
|
67981
67965
|
],
|
|
67982
67966
|
isError: true
|
|
67983
67967
|
};
|
|
67984
67968
|
}
|
|
67985
|
-
const
|
|
67986
|
-
let saveErrorText = "";
|
|
67969
|
+
const savedImages = [];
|
|
67987
67970
|
if (output_dir) {
|
|
67988
67971
|
try {
|
|
67989
67972
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
67990
|
-
const
|
|
67991
|
-
|
|
67992
|
-
|
|
67993
|
-
|
|
67994
|
-
|
|
67995
|
-
|
|
67996
|
-
})
|
|
67997
|
-
);
|
|
67998
|
-
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
|
+
}
|
|
67999
67979
|
} catch (error48) {
|
|
68000
|
-
|
|
68001
|
-
|
|
68002
|
-
\u26A0\uFE0F Failed to save images: ${getErrorMessage(error48)}`;
|
|
67980
|
+
console.error(`Failed to save images: ${getErrorMessage(error48)}`);
|
|
67981
|
+
savedImages.push(...images);
|
|
68003
67982
|
}
|
|
67983
|
+
} else {
|
|
67984
|
+
savedImages.push(...images);
|
|
68004
67985
|
}
|
|
67986
|
+
const savedPaths = savedImages.map((img) => img.savedPath).filter(Boolean);
|
|
68005
67987
|
const content = [
|
|
68006
67988
|
{
|
|
68007
67989
|
type: "text",
|
|
68008
|
-
text: `\u2705 Image generated successfully
|
|
67990
|
+
text: `\u2705 Image generated successfully.${savedPaths.length > 0 ? `
|
|
68009
67991
|
Saved to:
|
|
68010
|
-
${savedPaths.join("\n")}` : ""}
|
|
67992
|
+
${savedPaths.join("\n")}` : ""}`
|
|
68011
67993
|
},
|
|
68012
|
-
...
|
|
67994
|
+
...savedImages.map((img) => ({
|
|
67995
|
+
type: "image",
|
|
67996
|
+
data: img.data,
|
|
67997
|
+
mimeType: img.mimeType
|
|
67998
|
+
}))
|
|
68013
67999
|
];
|
|
68014
|
-
return { content };
|
|
68000
|
+
return { content, structuredContent: { images: savedImages, prompt } };
|
|
68015
68001
|
}
|
|
68016
|
-
async function generateVideo(
|
|
68017
|
-
const
|
|
68018
|
-
z3.object({
|
|
68019
|
-
prompt: z3.string().min(1),
|
|
68020
|
-
model: z3.string().default(DEFAULT_VIDEO_MODEL)
|
|
68021
|
-
}).strict(),
|
|
68022
|
-
rawArgs
|
|
68023
|
-
);
|
|
68024
|
-
if (!parsed.success) {
|
|
68025
|
-
return parsed.error;
|
|
68026
|
-
}
|
|
68027
|
-
const { prompt, model } = parsed.data;
|
|
68002
|
+
async function generateVideo(args) {
|
|
68003
|
+
const { prompt, model } = args;
|
|
68028
68004
|
if (IS_MOCK) {
|
|
68029
|
-
|
|
68030
|
-
|
|
68031
|
-
|
|
68032
|
-
type: "text",
|
|
68033
|
-
text: `[Mock] Video generation started.
|
|
68034
|
-
Operation name: mock-operations/123456
|
|
68035
|
-
Model: ${model}
|
|
68005
|
+
const opName2 = "mock-operations/123456";
|
|
68006
|
+
return textResult(
|
|
68007
|
+
`[Mock] Video generation started.
|
|
68036
68008
|
|
|
68037
|
-
|
|
68038
|
-
|
|
68039
|
-
|
|
68040
|
-
|
|
68009
|
+
Operation name: ${opName2}
|
|
68010
|
+
|
|
68011
|
+
Call get_video_status to check progress.`,
|
|
68012
|
+
{ operationName: opName2, prompt, status: "queued" }
|
|
68013
|
+
);
|
|
68041
68014
|
}
|
|
68042
68015
|
const operation = await getAi().models.generateVideos({
|
|
68043
|
-
model,
|
|
68016
|
+
model: model || DEFAULT_VIDEO_MODEL,
|
|
68044
68017
|
prompt,
|
|
68045
68018
|
config: { numberOfVideos: 1 }
|
|
68046
68019
|
});
|
|
68047
68020
|
const opName = operation.name ?? "unknown";
|
|
68048
|
-
return
|
|
68049
|
-
|
|
68050
|
-
{
|
|
68051
|
-
type: "text",
|
|
68052
|
-
text: `Video generation started (async \u2014 typically takes 2\u20135 minutes).
|
|
68021
|
+
return textResult(
|
|
68022
|
+
`Video generation started.
|
|
68053
68023
|
|
|
68054
68024
|
Operation name: ${opName}
|
|
68055
68025
|
|
|
68056
|
-
Call get_video_status
|
|
68057
|
-
|
|
68058
|
-
|
|
68059
|
-
Poll every ~30 seconds until done=true.`
|
|
68060
|
-
}
|
|
68061
|
-
]
|
|
68062
|
-
};
|
|
68063
|
-
}
|
|
68064
|
-
async function getVideoStatus(rawArgs) {
|
|
68065
|
-
const parsed = parseArgs(
|
|
68066
|
-
z3.object({
|
|
68067
|
-
operation_name: z3.string().min(1),
|
|
68068
|
-
output_dir: z3.string().optional()
|
|
68069
|
-
}).strict(),
|
|
68070
|
-
rawArgs
|
|
68026
|
+
Call get_video_status every ~30s until complete.`,
|
|
68027
|
+
{ operationName: opName, prompt, status: "started" }
|
|
68071
68028
|
);
|
|
68072
|
-
|
|
68073
|
-
|
|
68074
|
-
}
|
|
68075
|
-
const { operation_name, output_dir } = parsed.data;
|
|
68029
|
+
}
|
|
68030
|
+
async function getVideoStatus(args) {
|
|
68031
|
+
const { operation_name, output_dir } = args;
|
|
68076
68032
|
let op;
|
|
68077
68033
|
if (IS_MOCK) {
|
|
68078
68034
|
op = {
|
|
@@ -68090,7 +68046,8 @@ async function getVideoStatus(rawArgs) {
|
|
|
68090
68046
|
}
|
|
68091
68047
|
if (!op.done) {
|
|
68092
68048
|
return textResult(
|
|
68093
|
-
`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: [] }
|
|
68094
68051
|
);
|
|
68095
68052
|
}
|
|
68096
68053
|
if (op.error) {
|
|
@@ -68098,20 +68055,30 @@ async function getVideoStatus(rawArgs) {
|
|
|
68098
68055
|
content: [
|
|
68099
68056
|
{
|
|
68100
68057
|
type: "text",
|
|
68101
|
-
text: `Video generation failed: ${op.error.message
|
|
68058
|
+
text: `Video generation failed: ${op.error.message || "Unknown upstream error"}`
|
|
68102
68059
|
}
|
|
68103
68060
|
],
|
|
68061
|
+
structuredContent: {
|
|
68062
|
+
done: true,
|
|
68063
|
+
error: op.error.message,
|
|
68064
|
+
videos: []
|
|
68065
|
+
},
|
|
68104
68066
|
isError: true
|
|
68105
68067
|
};
|
|
68106
68068
|
}
|
|
68107
68069
|
const videos = (op.response?.generatedVideos ?? []).map((video) => video.video?.uri ?? "").filter(Boolean);
|
|
68108
68070
|
if (videos.length === 0) {
|
|
68109
|
-
return
|
|
68110
|
-
|
|
68111
|
-
|
|
68112
|
-
|
|
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
|
+
};
|
|
68113
68080
|
}
|
|
68114
|
-
const
|
|
68081
|
+
const videoResults = [];
|
|
68115
68082
|
const videoContents = [];
|
|
68116
68083
|
await Promise.all(
|
|
68117
68084
|
videos.map(async (url2, index) => {
|
|
@@ -68121,9 +68088,7 @@ ${JSON.stringify(op.response, null, 2)}`
|
|
|
68121
68088
|
} else {
|
|
68122
68089
|
const videoResp = await fetch(withApiKey(url2));
|
|
68123
68090
|
if (!videoResp.ok) {
|
|
68124
|
-
throw new Error(
|
|
68125
|
-
`Failed to download video: ${videoResp.status}`
|
|
68126
|
-
);
|
|
68091
|
+
throw new Error(`Failed to download video.`);
|
|
68127
68092
|
}
|
|
68128
68093
|
const arrayBuffer = await videoResp.arrayBuffer();
|
|
68129
68094
|
buffer = Buffer.from(arrayBuffer);
|
|
@@ -68136,55 +68101,66 @@ ${JSON.stringify(op.response, null, 2)}`
|
|
|
68136
68101
|
blob: buffer.toString("base64")
|
|
68137
68102
|
}
|
|
68138
68103
|
});
|
|
68104
|
+
let savedPath;
|
|
68139
68105
|
if (output_dir) {
|
|
68140
68106
|
try {
|
|
68141
68107
|
const fname = `video-${Date.now()}-${index + 1}.mp4`;
|
|
68142
|
-
|
|
68108
|
+
savedPath = path2.join(output_dir, fname);
|
|
68143
68109
|
await fs3.mkdir(output_dir, { recursive: true });
|
|
68144
|
-
await fs3.writeFile(
|
|
68145
|
-
savedPaths.push(fpath);
|
|
68110
|
+
await fs3.writeFile(savedPath, buffer);
|
|
68146
68111
|
} catch (error48) {
|
|
68147
68112
|
console.error(
|
|
68148
68113
|
`Failed to save video: ${getErrorMessage(error48)}`
|
|
68149
68114
|
);
|
|
68150
68115
|
}
|
|
68151
68116
|
}
|
|
68117
|
+
videoResults.push({ url: url2, savedPath });
|
|
68152
68118
|
})
|
|
68153
68119
|
);
|
|
68154
|
-
const
|
|
68120
|
+
const savedPaths = videoResults.map((v) => v.savedPath).filter(Boolean);
|
|
68121
|
+
const summaryLines = [
|
|
68155
68122
|
`Video generation complete!
|
|
68156
68123
|
|
|
68157
68124
|
Download URLs:
|
|
68158
68125
|
${videos.join("\n")}`
|
|
68159
68126
|
];
|
|
68160
68127
|
if (savedPaths.length > 0) {
|
|
68161
|
-
|
|
68128
|
+
summaryLines.push(`
|
|
68129
|
+
|
|
68162
68130
|
Saved to:
|
|
68163
68131
|
${savedPaths.join("\n")}`);
|
|
68164
|
-
} else if (output_dir) {
|
|
68165
|
-
lines.push(`
|
|
68166
|
-
\u26A0\uFE0F Failed to save videos to disk.`);
|
|
68167
68132
|
}
|
|
68168
68133
|
return {
|
|
68169
68134
|
content: [
|
|
68170
|
-
{ type: "text", text:
|
|
68135
|
+
{ type: "text", text: summaryLines.join("") },
|
|
68171
68136
|
...videoContents
|
|
68172
|
-
]
|
|
68137
|
+
],
|
|
68138
|
+
structuredContent: { done: true, videos: videoResults }
|
|
68173
68139
|
};
|
|
68174
68140
|
}
|
|
68175
68141
|
async function handleToolCall(name, args) {
|
|
68176
68142
|
try {
|
|
68177
68143
|
switch (name) {
|
|
68178
68144
|
case "analyze_media":
|
|
68179
|
-
return await analyzeMedia(
|
|
68145
|
+
return await analyzeMedia(
|
|
68146
|
+
ANALYZE_MEDIA_TOOL.inputSchema.parse(args)
|
|
68147
|
+
);
|
|
68180
68148
|
case "list_models":
|
|
68181
|
-
return await listModels(
|
|
68149
|
+
return await listModels(
|
|
68150
|
+
LIST_MODELS_TOOL.inputSchema.parse(args)
|
|
68151
|
+
);
|
|
68182
68152
|
case "generate_image":
|
|
68183
|
-
return await generateImage(
|
|
68153
|
+
return await generateImage(
|
|
68154
|
+
GENERATE_IMAGE_TOOL.inputSchema.parse(args)
|
|
68155
|
+
);
|
|
68184
68156
|
case "generate_video":
|
|
68185
|
-
return await generateVideo(
|
|
68157
|
+
return await generateVideo(
|
|
68158
|
+
GENERATE_VIDEO_TOOL.inputSchema.parse(args)
|
|
68159
|
+
);
|
|
68186
68160
|
case "get_video_status":
|
|
68187
|
-
return await getVideoStatus(
|
|
68161
|
+
return await getVideoStatus(
|
|
68162
|
+
GET_VIDEO_STATUS_TOOL.inputSchema.parse(args)
|
|
68163
|
+
);
|
|
68188
68164
|
default:
|
|
68189
68165
|
throw new Error(`Tool not found: ${name}`);
|
|
68190
68166
|
}
|
|
@@ -68195,6 +68171,9 @@ async function handleToolCall(name, args) {
|
|
|
68195
68171
|
error48.issues[0]?.message || error48.message
|
|
68196
68172
|
);
|
|
68197
68173
|
}
|
|
68174
|
+
if (isErrorWithStatusCode(error48)) {
|
|
68175
|
+
return createApiError(error48.message, error48.statusCode);
|
|
68176
|
+
}
|
|
68198
68177
|
return createInternalError(error48);
|
|
68199
68178
|
}
|
|
68200
68179
|
}
|