@codixfy/gemini
Version:
An npm package for nodejs that makes easier working with Gemini AI API. Includes some useful methods solving common tasks, helping quick and stable development.
201 lines (199 loc) • 6.08 kB
JavaScript
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
// src/providers/gemini.ts
var {
GoogleGenerativeAI,
HarmBlockThreshold,
HarmCategory
} = __require("@google/generative-ai");
var Base64 = __require("base64-js");
var Gemini = class {
genAI;
model;
currentModel;
apiKey;
constructor(apiKey, options) {
var _a, _b, _c, _d;
this.genAI = new GoogleGenerativeAI(apiKey);
this.apiKey = apiKey;
this.currentModel = "gemini-1.5-flash";
if (options == null ? void 0 : options.model) {
this.currentModel = options.model;
if (this.currentModel === "gemini-2.0-flash") {
this.currentModel += "-exp";
}
if (this.currentModel === "gemini-2.0-flash" && !(options == null ? void 0 : options.useLatestModel)) {
this.currentModel += "-latest";
}
}
this.model = this.genAI.getGenerativeModel({
model: this.currentModel,
safetySettings: [
{
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold: ((_a = options == null ? void 0 : options.safetySettings) == null ? void 0 : _a.blockDangerousContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE
},
{
category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
threshold: ((_b = options == null ? void 0 : options.safetySettings) == null ? void 0 : _b.blockExplicitContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE
},
{
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
threshold: ((_c = options == null ? void 0 : options.safetySettings) == null ? void 0 : _c.blockHarassmentContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE
},
{
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
threshold: ((_d = options == null ? void 0 : options.safetySettings) == null ? void 0 : _d.blockHateContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE
}
],
systemInstruction: (options == null ? void 0 : options.instructions) || void 0
});
}
// Used to send a message without any context
async ask(message, extra) {
const partsWithFiles = [];
if ((extra == null ? void 0 : extra.files) && extra.files.length > 0) {
if (this.currentModel === "gemini-pro-vision") {
throw new Error(
`This model does not support files. Current model: ${this.currentModel}`
);
}
for (const file of extra.files) {
partsWithFiles.push(
{
text: "Link: " + file
}
);
}
}
const contents = [
{
role: "user",
parts: [
{
text: message
},
...partsWithFiles
]
}
];
const result = await this.model.generateContentStream({ contents });
const buffer = [];
for await (const response of result.stream) {
buffer.push(response.text());
if (extra == null ? void 0 : extra.stream) {
extra.stream(response.text());
}
}
return buffer.join(" ");
}
createChat(chartContext) {
return new GeminiChat(
this.model,
chartContext === null ? [] : chartContext,
this.currentModel
);
}
};
var GeminiChat = class {
model;
chatContext;
currentModel;
constructor(model, chatContext, currentModel) {
this.model = model;
this.chatContext = chatContext;
this.currentModel = currentModel;
}
async send(message, extra) {
const partsWithFiles = [];
if ((extra == null ? void 0 : extra.files) && extra.files.length > 0) {
if (this.currentModel === "gemini-pro-vision") {
throw new Error(
`This model does not support images. Current model: ${this.currentModel}`
);
}
for (const file of extra.files) {
partsWithFiles.push(
{
text: "Link: " + file
}
);
}
}
if (!this.chatContext) {
this.chatContext = [];
}
this.chatContext.push({
role: "user",
parts: [
{
text: message
},
...partsWithFiles
]
});
const contents = this.chatContext;
const result = await this.model.generateContentStream({ contents });
const buffer = [];
for await (const response of result.stream) {
buffer.push(response.text());
if (extra == null ? void 0 : extra.stream) {
extra.stream(response.text());
}
}
return buffer.join(" ");
}
async reset() {
this.chatContext = [];
}
async save() {
return this.chatContext;
}
async load(context) {
this.chatContext = context;
}
};
var GeminiUtils = class {
static async fileToGenerativePart(file) {
const mimeType = await this.mimeTypeFromFile(file);
const image64 = await fetch(file).then((r) => r.arrayBuffer()).then((a) => Base64.fromByteArray(new Uint8Array(a)));
return {
inline_data: {
data: image64,
mime_type: mimeType
}
};
}
static async mimeTypeFromFile(file) {
const extension = file.split(".")[file.split(".").length - 1];
switch (extension) {
case "jpg":
case "jpeg":
return "image/jpeg";
case "png":
return "image/png";
case "gif":
return "image/gif";
case "webp":
return "image/webp";
case "mp4":
return "video/mp4";
case "wav":
return "audio/wav";
case "mp3":
return "audio/mp3";
case "aac":
return "audio/aac";
default:
throw new Error("Unsupported file type (${extension})");
}
}
};
export {
Gemini,
GeminiUtils
};