enotkrutoy commited on
Commit
a992a28
·
verified ·
1 Parent(s): 7136ebe

Upload 19 files

Browse files
Files changed (16) hide show
  1. .gitignore +63 -0
  2. App.tsx +283 -0
  3. Dockerfile +77 -0
  4. GEMINI.md +50 -0
  5. README0.md +20 -0
  6. constants.ts +18 -0
  7. examples.ts +60 -0
  8. index.html +45 -19
  9. index.tsx +20 -0
  10. metadata.json +7 -0
  11. package-lock.json +0 -0
  12. package.json +42 -0
  13. requirements.txt +11 -0
  14. tsconfig.json +32 -0
  15. types.ts +72 -0
  16. vite.config.ts +72 -0
.gitignore ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ # Logs
3
+
4
+ logs
5
+
6
+ *.log
7
+
8
+ npm-debug.log*
9
+
10
+ yarn-debug.log*
11
+
12
+ yarn-error.log*
13
+
14
+ pnpm-debug.log*
15
+
16
+ lerna-debug.log*
17
+
18
+
19
+
20
+ node_modules
21
+
22
+ dist
23
+
24
+ dist-ssr
25
+
26
+ *.local
27
+
28
+ .env
29
+
30
+
31
+
32
+ # Editor directories and files
33
+
34
+ .vscode/*
35
+
36
+ !.vscode/extensions.json
37
+
38
+ .idea
39
+
40
+ .DS_Store
41
+
42
+ *.suo
43
+
44
+ *.ntvs*
45
+
46
+ *.njsproj
47
+
48
+ *.sln
49
+
50
+ *.sw?
51
+
52
+
53
+
54
+ # Python
55
+
56
+ __pycache__/
57
+
58
+ *.pyc
59
+
60
+ .venv
61
+
62
+ venv/
63
+
App.tsx ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import React, { useState, useMemo } from 'react';
3
+
4
+ import { ToolDefinition, GeneratedCode, ToolType, FunctionDefinition, ParameterType } from './types';
5
+
6
+ import ToolForm from './components/ToolForm';
7
+
8
+ import CodeOutput from './components/CodeOutput';
9
+
10
+ import { generateAllCode } from './services/codeGenerator';
11
+
12
+ import { nmapScannerExample } from './examples';
13
+
14
+ import Button from './components/ui/Button';
15
+
16
+ import AiPrompt from './components/AiPrompt';
17
+
18
+ import { generateToolDefinitionFromPrompt } from './services/aiService';
19
+
20
+
21
+
22
+ const initialFunction: FunctionDefinition = {
23
+
24
+ id: crypto.randomUUID(),
25
+
26
+ name: 'example_function',
27
+
28
+ description: 'Краткое описание того, что делает эта функция.',
29
+
30
+ parameters: [
31
+
32
+ {
33
+
34
+ id: crypto.randomUUID(),
35
+
36
+ name: 'example_param',
37
+
38
+ type: ParameterType.STRING, // Исправлено с 'str' as any
39
+
40
+ description: 'Описание параметра.',
41
+
42
+ required: true,
43
+
44
+ },
45
+
46
+ ],
47
+
48
+ returnType: ParameterType.STRING, // Исправлено с 'str' as any
49
+
50
+ returnDescription: 'Описание возвращаемого значения.',
51
+
52
+ };
53
+
54
+
55
+
56
+ const initialToolDefinition: ToolDefinition = {
57
+
58
+ name: 'my_tool',
59
+
60
+ type: ToolType.UTILITY,
61
+
62
+ dependencies: '',
63
+
64
+ functions: [initialFunction],
65
+
66
+ };
67
+
68
+
69
+
70
+ const App: React.FC = () => {
71
+
72
+ const [toolDefinition, setToolDefinition] = useState<ToolDefinition>(initialToolDefinition);
73
+
74
+ const [aiPrompt, setAiPrompt] = useState<string>('');
75
+
76
+ const [isGenerating, setIsGenerating] = useState<boolean>(false);
77
+
78
+ const [aiError, setAiError] = useState<string | null>(null);
79
+
80
+
81
+
82
+ const generatedCode = useMemo<GeneratedCode | null>(() => {
83
+
84
+ try {
85
+
86
+ if (toolDefinition.name && toolDefinition.functions.length > 0 && toolDefinition.functions.every(f => f.name)) {
87
+
88
+ return generateAllCode(toolDefinition);
89
+
90
+ }
91
+
92
+ return null;
93
+
94
+ } catch (error) {
95
+
96
+ console.error("Error generating code:", error);
97
+
98
+ return null;
99
+
100
+ }
101
+
102
+ }, [toolDefinition]);
103
+
104
+
105
+
106
+ const loadNmapExample = () => {
107
+
108
+ setToolDefinition(nmapScannerExample);
109
+
110
+ };
111
+
112
+
113
+
114
+ const handleAiGenerate = async () => {
115
+
116
+ if (!aiPrompt.trim()) {
117
+
118
+ setAiError("Пожалуйста, введите описание инструмента.");
119
+
120
+ return;
121
+
122
+ }
123
+
124
+ setIsGenerating(true);
125
+
126
+ setAiError(null);
127
+
128
+ try {
129
+
130
+ const jsonString = await generateToolDefinitionFromPrompt(aiPrompt);
131
+
132
+
133
+
134
+ // Бэкенд уже должен был очистить markdown, но на всякий случай
135
+
136
+ const cleanedJsonString = jsonString.replace(/^```json\s*|\s*```$/g, '').trim();
137
+
138
+ const newToolDefinition = JSON.parse(cleanedJsonString);
139
+
140
+
141
+
142
+ // Добавим уникальные ID, так как AI их не генерирует
143
+
144
+ if (newToolDefinition.functions) {
145
+
146
+ newToolDefinition.functions.forEach((func: FunctionDefinition) => {
147
+
148
+ func.id = crypto.randomUUID();
149
+
150
+ if (func.parameters) {
151
+
152
+ func.parameters.forEach((param: any) => {
153
+
154
+ param.id = crypto.randomUUID();
155
+
156
+ });
157
+
158
+ } else {
159
+
160
+ func.parameters = []; // Убедимся, что параметры существуют
161
+
162
+ }
163
+
164
+ });
165
+
166
+ } else {
167
+
168
+ newToolDefinition.functions = []; // Убедимся, что функции существуют
169
+
170
+ }
171
+
172
+
173
+
174
+ setToolDefinition(newToolDefinition);
175
+
176
+
177
+
178
+ } catch (error) {
179
+
180
+ console.error("AI generation failed:", error);
181
+
182
+ setAiError(`Не удалось сгенерировать инструмент: ${error.message}. Проверьте консоль.`);
183
+
184
+ } finally {
185
+
186
+ setIsGenerating(false);
187
+
188
+ }
189
+
190
+ };
191
+
192
+
193
+
194
+ return (
195
+
196
+ <div className="min-h-screen bg-gray-900 text-gray-100 p-4 sm:p-6 lg:p-8">
197
+
198
+ <div className="max-w-screen-2xl mx-auto">
199
+
200
+ <header className="mb-8">
201
+
202
+ <div className="text-center">
203
+
204
+ <h1 className="text-4xl sm:text-5xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-sky-400 to-blue-600">
205
+
206
+ Gemini CLI Tool Generator
207
+
208
+ </h1>
209
+
210
+ <p className="mt-2 text-lg text-gray-400">
211
+
212
+ Создайте кастомные расширения, которые Gemini сможет вызывать для решения ваших задач.
213
+
214
+ </p>
215
+
216
+ </div>
217
+
218
+ <div className="text-center mt-4">
219
+
220
+ <Button onClick={loadNmapExample} variant="secondary">
221
+
222
+ Загрузить пример: Nmap Scanner
223
+
224
+ </Button>
225
+
226
+ </div>
227
+
228
+ </header>
229
+
230
+
231
+
232
+ <AiPrompt
233
+
234
+ prompt={aiPrompt}
235
+
236
+ setPrompt={setAiPrompt}
237
+
238
+ onGenerate={handleAiGenerate}
239
+
240
+ isLoading={isGenerating}
241
+
242
+ error={aiError}
243
+
244
+ />
245
+
246
+
247
+
248
+ <main className="grid grid-cols-1 xl:grid-cols-2 gap-8 mt-8">
249
+
250
+ <ToolForm toolDefinition={toolDefinition} setToolDefinition={setToolDefinition} />
251
+
252
+ <CodeOutput generatedCode={generatedCode} toolName={toolDefinition.name} />
253
+
254
+ </main>
255
+
256
+
257
+
258
+ <footer className="text-center mt-12 py-4 border-t border-gray-700">
259
+
260
+ <p className="text-gray-500">
261
+
262
+ Разработано с использованием React, Tailwind CSS и Gemini.
263
+
264
+ </p>
265
+
266
+ </footer>
267
+
268
+ </div>
269
+
270
+ </div>
271
+
272
+ );
273
+
274
+ };
275
+
276
+
277
+
278
+ export default App;
279
+
280
+
281
+
282
+
283
+
Dockerfile ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ # Этап 1: Сборка React-фронтенда
3
+
4
+ FROM node:18-slim AS build
5
+
6
+ WORKDIR /app
7
+
8
+
9
+
10
+ # Копируем package.json и устанавливаем npm зависимости
11
+
12
+ COPY package.json package-lock.json ./
13
+
14
+ RUN npm install
15
+
16
+
17
+
18
+ # Копируем остальной код фронтенда
19
+
20
+ COPY . .
21
+
22
+
23
+
24
+ # Собираем production build (создает папку 'dist')
25
+
26
+ RUN npm run build
27
+
28
+
29
+
30
+ # Этап 2: Настройка Python-сервера (FastAPI)
31
+
32
+ FROM python:3.10-slim
33
+
34
+ WORKDIR /app
35
+
36
+
37
+
38
+ # Установка переменных окружения
39
+
40
+ ENV PYTHONUNBUFFERED 1
41
+
42
+ ENV PYTHONDONTWRITEBYTECODE 1
43
+
44
+
45
+
46
+ # Копируем Python-зависимости и устанавливаем их
47
+
48
+ COPY requirements.txt .
49
+
50
+ RUN pip install --no-cache-dir -r requirements.txt
51
+
52
+
53
+
54
+ # Копируем код бэкенда (FastAPI)
55
+
56
+ COPY ./backend ./backend
57
+
58
+
59
+
60
+ # Копируем собранный фронтенд из Этапа 1
61
+
62
+ COPY --from=build /app/dist ./dist
63
+
64
+
65
+
66
+ # Порт 7860 - стандартный для HF Spaces
67
+
68
+ EXPOSE 7860
69
+
70
+ ENV PORT=7860
71
+
72
+
73
+
74
+ # Команда для запуска Uvicorn (FastAPI)
75
+
76
+ CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "7860"]
77
+
GEMINI.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Инструкция для Агента: Инструмент "nmap_scanner"
2
+
3
+ ## Описание
4
+
5
+ Этот инструмент предоставляет прямой доступ к сетевому сканеру Nmap для проведения разведки и обнаружения хостов в сети. Он относится к типу **UTILITY**. Используй его для анализа сетевой безопасности, инвентаризации устройств и проверки открытых портов.
6
+
7
+ ## Функции
8
+
9
+ ### `nmap_scanner:run_scan`
10
+
11
+ Запускает детальное сканирование Nmap на указанные цели. Позволяет гибко настраивать тип сканирования, определять службы и версии ПО.
12
+
13
+ **Параметры:**
14
+ - `targets` (*str*): Цели для сканирования (IP-адрес, домен, CIDR-диапазон). Например: '192.168.1.1', 'scanme.nmap.org', '10.0.0.0/24'. (обязательный)
15
+ - `ports` (*str*): Порты для сканирования. Например: '21-25,80,443', '1-1024'. (обязательный)
16
+ - `arguments` (*str*): Дополнительные аргументы командной строки Nmap. Например: '-sV -sC' для определения версий и запуска скриптов, или '-A' для агрессивного сканирования. (обязательный)
17
+
18
+ **Возвращает:**
19
+ *dict* - Результат сканирования в формате JSON, содержащий информацию о хостах, их состоянии, открытых портах, службах и версиях.
20
+
21
+ ---
22
+
23
+ ### `nmap_scanner:host_discovery`
24
+
25
+ Быстро обнаруживает активные (включенные) хосты в указанной сети с помощью 'ping scan' (`-sn`), не проводя полного сканирования портов.
26
+
27
+ **Параметры:**
28
+ - `network_cidr` (*str*): Сетевой диапазон в формате CIDR для обнаружения хостов. Например: '192.168.1.0/24'. (обязательный)
29
+
30
+ **Возвращает:**
31
+ *list* - Список IP-адресов активных хостов, обнаруженных в сети.
32
+
33
+ ## Примеры использования
34
+
35
+ **ВАЖНО:** Всегда используй формат `nmap_scanner:имя_функции()`.
36
+
37
+ **Пример 1: Обнаружение всех активных устройств в локальной сети**
38
+ ```
39
+ nmap_scanner:host_discovery(network_cidr="192.168.0.0/24")
40
+ ```
41
+
42
+ **Пример 2: Быстрое сканирование популярных портов на конкретном хосте**
43
+ ```
44
+ nmap_scanner:run_scan(targets="192.168.1.1", ports="1-1024", arguments="-T4")
45
+ ```
46
+
47
+ **Пример 3: Агрессивное сканирование веб-сервера для определения ОС, служб и уязвимостей**
48
+ ```
49
+ nmap_scanner:run_scan(targets="scanme.nmap.org", ports="80,443", arguments="-A -v")
50
+ ```
README0.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+ <img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
3
+ </div>
4
+
5
+ # Run and deploy your AI Studio app
6
+
7
+ This contains everything you need to run your app locally.
8
+
9
+ View your app in AI Studio: https://ai.studio/apps/drive/1DWLDNsbZ8bO_lQPzuDVQB3cpW92HgYCC
10
+
11
+ ## Run Locally
12
+
13
+ **Prerequisites:** Node.js
14
+
15
+
16
+ 1. Install dependencies:
17
+ `npm install`
18
+ 2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
19
+ 3. Run the app:
20
+ `npm run dev`
constants.ts ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { ToolType, ParameterType } from './types';
3
+
4
+ export const TOOL_TYPES: ToolType[] = Object.values(ToolType);
5
+ export const PARAMETER_TYPES: ParameterType[] = Object.values(ParameterType);
6
+
7
+ export const PARAMETER_TYPE_DESCRIPTIONS: Record<ParameterType, string> = {
8
+ [ParameterType.STRING]: 'Текстовая строка (e.g., "hello world").',
9
+ [ParameterType.INTEGER]: 'Целое число (e.g., 10, -5).',
10
+ [ParameterType.FLOAT]: 'Число с плавающей точкой (e.g., 3.14).',
11
+ [ParameterType.BOOLEAN]: 'Логическое значение (True или False).',
12
+ [ParameterType.LIST]: 'Упорядоченный список элементов (e.g., ["a", "b"]).',
13
+ [ParameterType.DICTIONARY]: 'Словарь пар ключ-значение (e.g., {"key": "value"}).'
14
+ };
15
+
16
+
17
+
18
+
examples.ts ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { ToolDefinition, ToolType, ParameterType } from './types';
3
+
4
+ export const nmapScannerExample: ToolDefinition = {
5
+ name: 'nmap_scanner',
6
+ type: ToolType.UTILITY,
7
+ dependencies: 'python-nmap',
8
+ functions: [
9
+ {
10
+ id: 'nmap-func-1',
11
+ name: 'run_scan',
12
+ description: 'Запускает сканирование Nmap на указанные цели с заданными аргументами. Позволяет выполнять гибкую разведку сети.',
13
+ parameters: [
14
+ {
15
+ id: 'nmap-param-1',
16
+ name: 'targets',
17
+ type: ParameterType.STRING,
18
+ description: "Цели для сканирования (IP, домен, CIDR). Например: '192.168.1.1', 'scanme.nmap.org', '10.0.0.0/24'.",
19
+ required: true,
20
+ },
21
+ {
22
+ id: 'nmap-param-2',
23
+ name: 'ports',
24
+ type: ParameterType.STRING,
25
+ description: "Порты для сканирования. Например: '21-25,80,443,8080'.",
26
+ required: true,
27
+ },
28
+ {
29
+ id: 'nmap-param-3',
30
+ name: 'arguments',
31
+ type: ParameterType.STRING,
32
+ description: "Дополнительные аргументы Nmap для тонкой настройки сканирования. Например: '-sV -sC -O'.",
33
+ required: true,
34
+ },
35
+ ],
36
+ returnType: ParameterType.DICTIONARY,
37
+ returnDescription: 'Результат сканирования в формате JSON, содержащий информацию о хостах, портах, службах и их версиях.',
38
+ },
39
+ {
40
+ id: 'nmap-func-2',
41
+ name: 'host_discovery',
42
+ description: 'Обнаруживает активные хосты в указанной сети (ping scan), не проводя сканирование портов.',
43
+ parameters: [
44
+ {
45
+ id: 'nmap-param-4',
46
+ name: 'network_cidr',
47
+ type: ParameterType.STRING,
48
+ description: "Сетевой диапазон в формате CIDR для обнаружения хостов. Например: '192.168.1.0/24'.",
49
+ required: true,
50
+ },
51
+ ],
52
+ returnType: ParameterType.LIST,
53
+ returnDescription: 'Список IP-адресов активных хостов, обнаруженных в сети.',
54
+ },
55
+ ],
56
+ };
57
+
58
+
59
+
60
+
index.html CHANGED
@@ -1,19 +1,45 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>FastMCP Tool Generator</title>
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
10
+ <style>
11
+ /* Custom scrollbar for webkit browsers */
12
+ ::-webkit-scrollbar {
13
+ width: 8px;
14
+ height: 8px;
15
+ }
16
+ ::-webkit-scrollbar-track {
17
+ background: #1f2937; /* bg-gray-800 */
18
+ }
19
+ ::-webkit-scrollbar-thumb {
20
+ background: #4b5563; /* bg-gray-600 */
21
+ border-radius: 4px;
22
+ }
23
+ ::-webkit-scrollbar-thumb:hover {
24
+ background: #6b7280; /* bg-gray-500 */
25
+ }
26
+ </style>
27
+ <script type="importmap">
28
+ {
29
+ "imports": {
30
+ "react": "https://aistudiocdn.com/react@^19.2.0",
31
+ "react-dom/": "https://aistudiocdn.com/react-dom@^19.2.0/",
32
+ "react/": "https://aistudiocdn.com/react@^19.2.0/",
33
+ "@google/genai": "https://aistudiocdn.com/@google/genai@^1.29.0"
34
+ }
35
+ }
36
+ </script>
37
+ <link rel="stylesheet" href="/index.css">
38
+ </head>
39
+ <body class="bg-gray-900 text-gray-100">
40
+ <div id="root"></div>
41
+ <script type="module" src="/index.tsx"></script>
42
+ </body>
43
+ </html>
44
+
45
+
index.tsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import React from 'react';
3
+ import ReactDOM from 'react-dom/client';
4
+ import App from './App';
5
+
6
+ const rootElement = document.getElementById('root');
7
+ if (!rootElement) {
8
+ throw new Error("Could not find root element to mount to");
9
+ }
10
+
11
+ const root = ReactDOM.createRoot(rootElement);
12
+ root.render(
13
+ <React.StrictMode>
14
+ <App />
15
+ </React.StrictMode>
16
+ );
17
+
18
+
19
+
20
+
metadata.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Copy of Copy of Copy of FastMCP Tool Generator",
3
+ "description": "A web application to generate complete, self-contained, and deployable FastMCP tool boilerplates for Gemini CLI based on user's technical requirements. It creates all necessary files including server logic, setup configuration, and agent instructions.",
4
+ "requestFramePermissions": []
5
+ }
6
+
7
+
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ {
3
+ "name": "fastmcp-tool-generator-hf",
4
+ "version": "0.0.0",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "autoprefixer": "^10.4.19",
14
+ "axios": "^1.7.2",
15
+ "highlight.js": "^11.9.0",
16
+ "jszip": "^3.10.1",
17
+ "postcss": "^8.4.38",
18
+ "react": "^18.2.0",
19
+ "react-dom": "^18.2.0",
20
+ "react-hot-toast": "^2.4.1",
21
+ "tailwindcss": "^3.4.4"
22
+ },
23
+ "devDependencies": {
24
+ "@types/highlight.js": "^10.1.0",
25
+ "@types/jszip": "^3.10.1",
26
+ "@types/react": "^18.2.66",
27
+ "@types/react-dom": "^18.2.22",
28
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
29
+ "@typescript-eslint/parser": "^7.2.0",
30
+ "@vitejs/plugin-react": "^4.2.1",
31
+ "eslint": "^8.57.0",
32
+ "eslint-plugin-react-hooks": "^4.6.0",
33
+ "eslint-plugin-react-refresh": "^0.4.6",
34
+ "typescript": "^5.2.2",
35
+ "vite": "^5.2.0"
36
+ }
37
+ }
38
+
39
+
40
+
41
+
42
+
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 
2
+ fastapi
3
+
4
+ uvicorn[standard]
5
+
6
+ google-generativeai
7
+
8
+ pydantic
9
+
10
+ python-dotenv
11
+
tsconfig.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "experimentalDecorators": true,
5
+ "useDefineForClassFields": false,
6
+ "module": "ESNext",
7
+ "lib": [
8
+ "ES2022",
9
+ "DOM",
10
+ "DOM.Iterable"
11
+ ],
12
+ "skipLibCheck": true,
13
+ "types": [
14
+ "node"
15
+ ],
16
+ "moduleResolution": "bundler",
17
+ "isolatedModules": true,
18
+ "moduleDetection": "force",
19
+ "allowJs": true,
20
+ "jsx": "react-jsx",
21
+ "paths": {
22
+ "@/*": [
23
+ "./*"
24
+ ]
25
+ },
26
+ "allowImportingTsExtensions": true,
27
+ "noEmit": true
28
+ }
29
+ }
30
+
31
+
32
+
types.ts ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ export enum ToolType {
3
+ REST_API = 'REST_API',
4
+ CLI = 'CLI',
5
+ DATABASE = 'DATABASE',
6
+ CUSTOM = 'CUSTOM',
7
+ UTILITY = 'UTILITY',
8
+ CALCULATOR = 'CALCULATOR',
9
+ CONVERTER = 'CONVERTER'
10
+ }
11
+
12
+ export enum ParameterType {
13
+ STRING = 'str',
14
+ INTEGER = 'int',
15
+ FLOAT = 'float',
16
+ BOOLEAN = 'bool',
17
+ LIST = 'list',
18
+ DICTIONARY = 'dict'
19
+ }
20
+
21
+ export interface ParameterDefinition {
22
+ id: string;
23
+ name: string;
24
+ type: ParameterType;
25
+ description: string;
26
+ required: boolean;
27
+ }
28
+
29
+ export interface FunctionDefinition {
30
+ id: string;
31
+ name: string;
32
+ description: string;
33
+ parameters: ParameterDefinition[];
34
+ returnType: ParameterType;
35
+ returnDescription: string;
36
+ }
37
+
38
+ export interface ToolDefinition {
39
+ name: string;
40
+ type: ToolType;
41
+ dependencies: string;
42
+ functions: FunctionDefinition[];
43
+ }
44
+
45
+ export interface GeneratedCode {
46
+ setupPy: string;
47
+ serverPy: string;
48
+ settingsJson: string;
49
+ geminiMd: string;
50
+ examplesMd: string;
51
+ }
52
+
53
+ // Экспортируем для использования в AI промпте
54
+ export const initialFunctionForPrompt: Omit<FunctionDefinition, 'id'> = {
55
+ name: 'example_function',
56
+ description: 'Краткое описание того, что делает эта функция.',
57
+ parameters: [
58
+ {
59
+ id: 'param-id-1', // id здесь для примера, в реальности он генерируется
60
+ name: 'example_param',
61
+ type: ParameterType.STRING,
62
+ description: 'Описание параметра.',
63
+ required: true,
64
+ },
65
+ ],
66
+ returnType: ParameterType.STRING,
67
+ returnDescription: 'Описание возвращаемого значения.',
68
+ };
69
+
70
+
71
+
72
+
vite.config.ts ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import path from 'path';
2
+
3
+ import { defineConfig, loadEnv } from 'vite';
4
+
5
+ import react from '@vitejs/plugin-react';
6
+
7
+
8
+
9
+ export default defineConfig(({ mode }) => {
10
+
11
+ const env = loadEnv(mode, '.', '');
12
+
13
+
14
+
15
+ // Порт для FastAPI (бэкенда) при локальной разработке
16
+
17
+ const PYTHON_BACKEND_PORT = 8000;
18
+
19
+
20
+
21
+ return {
22
+
23
+ server: {
24
+
25
+ // Используем порт 3000 для Vite (фронтенда)
26
+
27
+ port: 3000,
28
+
29
+ host: '0.0.0.0',
30
+
31
+ proxy: {
32
+
33
+ // Перенаправляем все /api запросы на наш Python бэкенд
34
+
35
+ '/api': {
36
+
37
+ target: `http://127.0.0.1:${PYTHON_BACKEND_PORT}`, // ИСПРАВЛЕНО
38
+
39
+ changeOrigin: true,
40
+
41
+ secure: false,
42
+
43
+ }
44
+
45
+ }
46
+
47
+ },
48
+
49
+ plugins: [react()],
50
+
51
+ define: {
52
+
53
+ // Ключ API БОЛЬШЕ НЕ НУЖЕН в define!
54
+
55
+ },
56
+
57
+ resolve: {
58
+
59
+ alias: {
60
+
61
+ '@': path.resolve(__dirname, '.'),
62
+
63
+ }
64
+
65
+ }
66
+
67
+ };
68
+
69
+ });
70
+
71
+
72
+