Spaces:
Configuration error
Configuration error
| import React, { useState, useMemo } from 'react'; | |
| import { ToolDefinition, GeneratedCode, ToolType, FunctionDefinition, ParameterType } from './types'; | |
| import ToolForm from './components/ToolForm'; | |
| import CodeOutput from './components/CodeOutput'; | |
| import { generateAllCode } from './services/codeGenerator'; | |
| import { nmapScannerExample } from './examples'; | |
| import Button from './components/ui/Button'; | |
| import AiPrompt from './components/AiPrompt'; | |
| import { generateToolDefinitionFromPrompt } from './services/aiService'; | |
| const initialFunction: FunctionDefinition = { | |
| id: crypto.randomUUID(), | |
| name: 'example_function', | |
| description: 'Краткое описание того, что делает эта функция.', | |
| parameters: [ | |
| { | |
| id: crypto.randomUUID(), | |
| name: 'example_param', | |
| type: ParameterType.STRING, // Исправлено с 'str' as any | |
| description: 'Описание параметра.', | |
| required: true, | |
| }, | |
| ], | |
| returnType: ParameterType.STRING, // Исправлено с 'str' as any | |
| returnDescription: 'Описание возвращаемого значения.', | |
| }; | |
| const initialToolDefinition: ToolDefinition = { | |
| name: 'my_tool', | |
| type: ToolType.UTILITY, | |
| dependencies: '', | |
| functions: [initialFunction], | |
| }; | |
| const App: React.FC = () => { | |
| const [toolDefinition, setToolDefinition] = useState<ToolDefinition>(initialToolDefinition); | |
| const [aiPrompt, setAiPrompt] = useState<string>(''); | |
| const [isGenerating, setIsGenerating] = useState<boolean>(false); | |
| const [aiError, setAiError] = useState<string | null>(null); | |
| const generatedCode = useMemo<GeneratedCode | null>(() => { | |
| try { | |
| if (toolDefinition.name && toolDefinition.functions.length > 0 && toolDefinition.functions.every(f => f.name)) { | |
| return generateAllCode(toolDefinition); | |
| } | |
| return null; | |
| } catch (error) { | |
| console.error("Error generating code:", error); | |
| return null; | |
| } | |
| }, [toolDefinition]); | |
| const loadNmapExample = () => { | |
| setToolDefinition(nmapScannerExample); | |
| }; | |
| const handleAiGenerate = async () => { | |
| if (!aiPrompt.trim()) { | |
| setAiError("Пожалуйста, введите описание инструмента."); | |
| return; | |
| } | |
| setIsGenerating(true); | |
| setAiError(null); | |
| try { | |
| const jsonString = await generateToolDefinitionFromPrompt(aiPrompt); | |
| // Бэкенд уже должен был очистить markdown, но на всякий случай | |
| const cleanedJsonString = jsonString.replace(/^```json\s*|\s*```$/g, '').trim(); | |
| const newToolDefinition = JSON.parse(cleanedJsonString); | |
| // Добавим уникальные ID, так как AI их не генерирует | |
| if (newToolDefinition.functions) { | |
| newToolDefinition.functions.forEach((func: FunctionDefinition) => { | |
| func.id = crypto.randomUUID(); | |
| if (func.parameters) { | |
| func.parameters.forEach((param: any) => { | |
| param.id = crypto.randomUUID(); | |
| }); | |
| } else { | |
| func.parameters = []; // Убедимся, что параметры существуют | |
| } | |
| }); | |
| } else { | |
| newToolDefinition.functions = []; // Убедимся, что функции существуют | |
| } | |
| setToolDefinition(newToolDefinition); | |
| } catch (error) { | |
| console.error("AI generation failed:", error); | |
| setAiError(`Не удалось сгенерировать инструмент: ${error.message}. Проверьте консоль.`); | |
| } finally { | |
| setIsGenerating(false); | |
| } | |
| }; | |
| return ( | |
| <div className="min-h-screen bg-gray-900 text-gray-100 p-4 sm:p-6 lg:p-8"> | |
| <div className="max-w-screen-2xl mx-auto"> | |
| <header className="mb-8"> | |
| <div className="text-center"> | |
| <h1 className="text-4xl sm:text-5xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-sky-400 to-blue-600"> | |
| Gemini CLI Tool Generator | |
| </h1> | |
| <p className="mt-2 text-lg text-gray-400"> | |
| Создайте кастомные расширения, которые Gemini сможет вызывать для решения ваших задач. | |
| </p> | |
| </div> | |
| <div className="text-center mt-4"> | |
| <Button onClick={loadNmapExample} variant="secondary"> | |
| Загрузить пример: Nmap Scanner | |
| </Button> | |
| </div> | |
| </header> | |
| <AiPrompt | |
| prompt={aiPrompt} | |
| setPrompt={setAiPrompt} | |
| onGenerate={handleAiGenerate} | |
| isLoading={isGenerating} | |
| error={aiError} | |
| /> | |
| <main className="grid grid-cols-1 xl:grid-cols-2 gap-8 mt-8"> | |
| <ToolForm toolDefinition={toolDefinition} setToolDefinition={setToolDefinition} /> | |
| <CodeOutput generatedCode={generatedCode} toolName={toolDefinition.name} /> | |
| </main> | |
| <footer className="text-center mt-12 py-4 border-t border-gray-700"> | |
| <p className="text-gray-500"> | |
| Разработано с использованием React, Tailwind CSS и Gemini. | |
| </p> | |
| </footer> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default App; | |