Skip to content

Commit 4afeecf

Browse files
authored
Update and rename README.md to Gemini.js
1 parent c1b62ba commit 4afeecf

2 files changed

Lines changed: 171 additions & 19 deletions

File tree

Gemini.js

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Name: Gemini AI
2+
// ID: gemini
3+
// Description: Интеграция с актуальными моделями Google Gemini API.
4+
// License: MIT
5+
// Author: Ваше Имя/Никнейм
6+
7+
(function (Scratch) {
8+
'use strict';
9+
10+
class GeminiExtension {
11+
constructor() {
12+
this.apiKey = '';
13+
this.model = 'gemini-2.5-flash';
14+
this.baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models';
15+
}
16+
17+
getInfo() {
18+
return {
19+
id: 'gemini',
20+
name: 'Gemini AI',
21+
color1: '#4285F4',
22+
color2: '#EA4335',
23+
color3: '#FBBC04',
24+
blocks: [
25+
{
26+
opcode: 'setApiKey',
27+
blockType: Scratch.BlockType.COMMAND,
28+
text: 'задать API ключ [API_KEY]',
29+
arguments: {
30+
API_KEY: {
31+
type: Scratch.ArgumentType.STRING,
32+
defaultValue: 'ваш_ключ_тут'
33+
}
34+
}
35+
},
36+
{
37+
opcode: 'setModel',
38+
blockType: Scratch.BlockType.COMMAND,
39+
text: 'использовать модель [MODEL]',
40+
arguments: {
41+
MODEL: {
42+
type: Scratch.ArgumentType.STRING,
43+
defaultValue: 'gemini-2.5-flash',
44+
menu: 'models'
45+
}
46+
}
47+
},
48+
'---',
49+
{
50+
opcode: 'askGemini',
51+
blockType: Scratch.BlockType.REPORTER,
52+
text: 'спросить у Gemini [PROMPT]',
53+
arguments: {
54+
PROMPT: {
55+
type: Scratch.ArgumentType.STRING,
56+
defaultValue: 'Привет!'
57+
}
58+
}
59+
},
60+
{
61+
opcode: 'askGeminiWithContext',
62+
blockType: Scratch.BlockType.REPORTER,
63+
text: 'спросить у Gemini [PROMPT] контекст [CONTEXT]',
64+
arguments: {
65+
PROMPT: {
66+
type: Scratch.ArgumentType.STRING,
67+
defaultValue: 'Ответь на вопрос'
68+
},
69+
CONTEXT: {
70+
type: Scratch.ArgumentType.STRING,
71+
defaultValue: 'Ты полезный помощник'
72+
}
73+
}
74+
}
75+
],
76+
menus: {
77+
models: {
78+
acceptReporters: true, // Позволяет вставлять овальные блоки вместо выбора из меню
79+
items: [
80+
{ text: 'Gemini 2.5 Flash ⚡', value: 'gemini-2.5-flash' },
81+
{ text: 'Gemini 2.5 Pro 🧠', value: 'gemini-2.5-pro' },
82+
{ text: 'Gemini 2.0 Flash', value: 'gemini-2.0-flash' },
83+
{ text: 'Gemini 1.5 Pro', value: 'gemini-1.5-pro' },
84+
{ text: 'Gemini 1.5 Flash', value: 'gemini-1.5-flash' }
85+
]
86+
}
87+
}
88+
};
89+
}
90+
91+
setApiKey(args) {
92+
this.apiKey = String(args.API_KEY).trim();
93+
if (!this.apiKey) {
94+
console.warn('[Gemini] API ключ не задан или пуст');
95+
}
96+
}
97+
98+
setModel(args) {
99+
this.model = String(args.MODEL).trim();
100+
}
101+
102+
async askGemini(args) {
103+
const prompt = String(args.PROMPT || '');
104+
return await this._sendRequest(prompt, 'Ты полезный помощник. Отвечай кратко и по делу.');
105+
}
106+
107+
async askGeminiWithContext(args) {
108+
const prompt = String(args.PROMPT || '');
109+
const context = String(args.CONTEXT || 'Ты полезный помощник. Отвечай кратко и по делу.');
110+
return await this._sendRequest(prompt, context);
111+
}
112+
113+
async _sendRequest(prompt, context) {
114+
if (!this.apiKey) {
115+
return '❌ Ошибка: API ключ не задан. Используй блок "задать API ключ"';
116+
}
117+
118+
if (!prompt.trim()) {
119+
return '❌ Ошибка: пустой запрос';
120+
}
121+
122+
try {
123+
const url = `${this.baseUrl}/${this.model}:generateContent?key=${this.apiKey}`;
124+
125+
// Правильная структура JSON-запроса для Gemini API с системными инструкциями
126+
const payload = {
127+
contents: [{
128+
parts: [{ text: prompt }]
129+
}],
130+
systemInstruction: {
131+
parts: [{ text: context }]
132+
}
133+
};
134+
135+
const response = await fetch(url, {
136+
method: 'POST',
137+
headers: {
138+
'Content-Type': 'application/json'
139+
},
140+
body: JSON.stringify(payload)
141+
});
142+
143+
if (!response.ok) {
144+
let errorMsg = `HTTP ${response.status}`;
145+
try {
146+
const errorData = await response.json();
147+
errorMsg += `: ${errorData.error?.message || 'Неизвестная ошибка'}`;
148+
} catch (_) {
149+
errorMsg += `: ${response.statusText}`;
150+
}
151+
throw new Error(errorMsg);
152+
}
153+
154+
const data = await response.json();
155+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
156+
157+
if (!text) {
158+
return '⚠️ Ответ от модели пуст или заблокирован фильтрами безопасности.';
159+
}
160+
161+
return text;
162+
163+
} catch (error) {
164+
console.error('[Gemini] Ошибка запроса:', error);
165+
return `⚠️ Ошибка: ${error.message}`;
166+
}
167+
}
168+
}
169+
170+
Scratch.extensions.register(new GeminiExtension());
171+
})(Scratch);

README.md

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)