commit 83cfcd9fb1347d55bc119d8b83adf7dc53c9a589
Author: Mikan <72257910+Mikan-DS@users.noreply.github.com>
Date: Mon Jun 2 14:16:03 2025 +0300
initial
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5b45655
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/react_app_map.txt
+/instructions.md
+/prompt.md
+/workingon.md
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/G4F.iml b/.idea/G4F.iml
new file mode 100644
index 0000000..961e841
--- /dev/null
+++ b/.idea/G4F.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..aecbf0c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c9c1627
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ReactDev/__init__.py b/ReactDev/__init__.py
new file mode 100644
index 0000000..59a387a
--- /dev/null
+++ b/ReactDev/__init__.py
@@ -0,0 +1,111 @@
+# Инициализация пакета
+import os
+
+from .core.ai_interface import AIInterface
+from .core.project_map import ProjectMap
+from .core.file_analyzer import FileAnalyzer
+from .core.commands import CommandGenerator
+from .utils.logger import log
+from .utils.file_utils import read_file, write_file
+from .config import REACT_PROJECT_PATH
+
+__all__ = ["AIInterface", "ProjectMap", "FileAnalyzer", "CommandGenerator", "run_workflow"]
+
+
+def ensure_default_files():
+ """
+ Проверяет наличие необходимых файлов и создает их с базовым содержимым, если они отсутствуют.
+ """
+ default_files = {
+ "workingon.md": "/path/to/react/project/src/Auth.tsx",
+ "prompt.md": "Добавить функцию авторизации в файл Auth.tsx",
+ "instructions.md": "# Инструкции для ИИ\n\n1. Функции должны быть написаны в TypeScript.\n2. Используйте современные практики React (например, хуки).\n3. При создании новых компонентов добавьте комментарии.",
+ }
+
+ for file_name, content in default_files.items():
+ if not os.path.exists(file_name):
+ log(f"File {file_name} not found. Creating it with default content.")
+ write_file(file_name, content)
+
+
+def parse_workingon_content(content: str) -> dict:
+ """
+ Парсит содержимое файла workingon.md.
+ Возвращает словарь с путем к файлу и дополнительным контекстом.
+ """
+ lines = content.strip().split("\n")
+ result = {"file_path": None, "context": ""}
+
+ if lines:
+ # Первая строка — путь к файлу
+ result["file_path"] = lines[0].strip()
+ # Остальные строки — дополнительный контекст
+ result["context"] = "\n".join(lines[1:]).strip()
+
+ return result
+
+
+
+def run_workflow():
+ """
+ Основной алгоритм работы библиотеки ReactDev.
+ 1. Создает карту структуры проекта.
+ 2. Анализирует файлы на наличие функций.
+ 3. Отправляет запрос к ИИ с контекстом.
+ 4. Генерирует план модификации.
+ """
+ log("Starting ReactDev workflow...")
+
+ # Шаг 0: Убедиться, что все необходимые файлы существуют
+ ensure_default_files()
+
+ # Шаг 1: Создание карты структуры проекта
+ project_map = ProjectMap(REACT_PROJECT_PATH)
+ project_structure = project_map.generate_map()
+ project_map.save_map()
+
+ log(f"Generated project structure:\n{project_structure}")
+
+ # Шаг 2: Чтение и парсинг workingon.md
+ workingon_content = read_file("workingon.md")
+ workingon_data = parse_workingon_content(workingon_content)
+
+ target_file = workingon_data["file_path"]
+ additional_context = workingon_data["context"]
+
+ if target_file and not os.path.exists(target_file):
+ log(f"Target file {target_file} does not exist.", level="error")
+ return
+
+ # Шаг 3: Анализ целевого файла (если указан)
+ functions_info = {}
+ if target_file:
+ file_analyzer = FileAnalyzer()
+ functions_info = file_analyzer.analyze_file(target_file)
+ log(f"Analyzed functions in {target_file}: {functions_info}")
+
+ # Шаг 4: Отправка запроса к ИИ
+ ai_interface = AIInterface()
+ user_prompt = read_file("prompt.md").strip()
+
+ # Добавляем дополнительный контекст из workingon.md
+ full_context = {
+ "project_structure": project_structure,
+ "target_file": target_file,
+ "functions_info": functions_info,
+ "additional_context": additional_context,
+ }
+
+ ai_response = ai_interface.analyze_project(user_prompt, full_context)
+ log(f"AI response: {ai_response}")
+
+ # Шаг 5: Генерация плана модификации
+ command_generator = CommandGenerator()
+ modifications = ai_response.get("modifications", [])
+ modification_plan = command_generator.generate_commands(modifications)
+
+ with open("modification_plan.md", "w") as f:
+ f.write(modification_plan)
+
+ log(f"Generated modification plan:\n{modification_plan}")
+ log("ReactDev workflow completed.")
diff --git a/ReactDev/config.py b/ReactDev/config.py
new file mode 100644
index 0000000..e9da3ac
--- /dev/null
+++ b/ReactDev/config.py
@@ -0,0 +1,4 @@
+REACT_PROJECT_PATH = r'C:\Users\Mikan\PycharmProjects\tisbiProFi\frontend\react-source'
+OPENAI_API_KEY = "secret" # Замените на ваш API-ключ
+OPENAI_BASE_URL = "http://localhost:51337/v1" # Базовый URL для OpenAI
+DEFAULT_MODEL = "gpt-4o-mini" # Модель по умолчанию
diff --git a/ReactDev/core/ai_interface.py b/ReactDev/core/ai_interface.py
new file mode 100644
index 0000000..610a79b
--- /dev/null
+++ b/ReactDev/core/ai_interface.py
@@ -0,0 +1,62 @@
+from openai import OpenAI
+from ..config import OPENAI_API_KEY, OPENAI_BASE_URL, DEFAULT_MODEL
+from ..utils.logger import log
+
+class AIInterface:
+ def __init__(self):
+ self.client = OpenAI(
+ api_key=OPENAI_API_KEY,
+ base_url=OPENAI_BASE_URL,
+ )
+
+ def send_request(self, prompt: str, context: dict = None) -> dict:
+ """
+ Отправляет запрос на эндпоинт ИИ через OpenAI и возвращает ответ.
+ """
+ try:
+ log(f"Sending request to AI endpoint with prompt: {prompt}")
+
+ # Подготовка сообщений для чат-комплитшена
+ messages = [{"role": "user", "content": prompt}]
+ if context:
+ # Преобразуем контекст в строку
+ context_str = self._format_context(context)
+ messages.append({"role": "system", "content": context_str})
+
+ # Создание запроса к OpenAI
+ response = self.client.chat.completions.create(
+ model=DEFAULT_MODEL,
+ messages=[{"role": "user", "content": "Write a poem about a tree"}],
+ stream=False, # Пока отключаем стриминг для простоты
+ )
+
+ # Обработка ответа
+ return {"response": response.choices[0].message.content}
+
+ except Exception as e:
+ log(f"Error communicating with AI endpoint: {e}", level="error")
+ raise
+
+ def _format_context(self, context: dict) -> str:
+ """
+ Преобразует контекст в строку для передачи в OpenAI API.
+ """
+ formatted_context = []
+ for key, value in context.items():
+ formatted_context.append(f"{key}: {value}")
+ return "\n".join(formatted_context)
+
+
+ def analyze_project(self, project_structure: str, prompt: str) -> dict:
+ """
+ Анализирует структуру проекта и запрос пользователя через ИИ.
+ """
+ context = {"project_structure": project_structure}
+ return self.send_request(prompt, context)
+
+ def request_additional_info(self, message: str) -> str:
+ """
+ Запрашивает дополнительную информацию у пользователя.
+ """
+ log("Requesting additional information from user.")
+ return input(f"{message}\n> ")
\ No newline at end of file
diff --git a/ReactDev/core/commands.py b/ReactDev/core/commands.py
new file mode 100644
index 0000000..616d746
--- /dev/null
+++ b/ReactDev/core/commands.py
@@ -0,0 +1,26 @@
+from ..utils.logger import log
+
+class CommandGenerator:
+ def __init__(self):
+ pass
+
+ def generate_commands(self, modifications: list) -> str:
+ """
+ Генерирует план модификации на основе анализа ИИ.
+ """
+ log("Generating modification plan...")
+ commands = []
+ for mod in modifications:
+ action = mod.get("action")
+ file = mod.get("file")
+ function = mod.get("function")
+ code = mod.get("code", "")
+
+ if action == "CREATE":
+ commands.append(f"CREATE {function} {file}")
+ elif action == "DELETE":
+ commands.append(f"DELETE {function} {file}")
+ elif action == "MODIFY":
+ commands.append(f"MODIFY {function} {file}")
+ commands.append(f"```ts\n{code}\n```")
+ return "\n".join(commands)
\ No newline at end of file
diff --git a/ReactDev/core/file_analyzer.py b/ReactDev/core/file_analyzer.py
new file mode 100644
index 0000000..44046f6
--- /dev/null
+++ b/ReactDev/core/file_analyzer.py
@@ -0,0 +1,37 @@
+import esprima
+from ..utils.logger import log
+
+class FileAnalyzer:
+ def __init__(self):
+ pass
+
+ def analyze_file(self, file_path: str) -> dict:
+ """
+ Анализирует файл и извлекает информацию о функциях.
+ """
+ log(f"Analyzing file: {file_path}")
+ with open(file_path, "r") as f:
+ code = f.read()
+
+ try:
+ parsed = esprima.parseScript(code, loc=True)
+ functions = self._extract_functions(parsed)
+ return functions
+ except Exception as e:
+ log(f"Error parsing file {file_path}: {e}", level="error")
+ return {}
+
+ def _extract_functions(self, ast: dict) -> dict:
+ """
+ Извлекает информацию о функциях из AST.
+ """
+ functions = {}
+ for node in ast.body:
+ if node.type == "FunctionDeclaration":
+ name = node.id.name
+ params = [param.name for param in node.params]
+ functions[name] = {
+ "params": params,
+ "return_type": "unknown", # Тип возвращаемого значения не всегда доступен
+ }
+ return functions
\ No newline at end of file
diff --git a/ReactDev/core/project_map.py b/ReactDev/core/project_map.py
new file mode 100644
index 0000000..fa7538a
--- /dev/null
+++ b/ReactDev/core/project_map.py
@@ -0,0 +1,81 @@
+import os
+from pathlib import Path
+
+from pathspec import PathSpec
+from pathspec.patterns import GitWildMatchPattern
+
+from ..utils.logger import log
+
+
+class ProjectMap:
+ def __init__(self, project_path: str):
+ self.project_path = project_path
+ self.gitignore_rules = self._load_gitignore()
+
+ def generate_map(self) -> str:
+ """
+ Создает карту структуры проекта, игнорируя файлы из .gitignore и директорию .git/.
+ """
+ log("Generating project structure map...")
+ structure = self._traverse_directory(self.project_path)
+ return structure
+
+ def _traverse_directory(self, path: str, level: int = 0) -> str:
+ """
+ Рекурсивно обходит директории и формирует строку структуры,
+ игнорируя файлы и директории из .gitignore и .git/.
+ """
+ indent = " " * level
+ result = ""
+ for entry in sorted(os.listdir(path)):
+ full_path = os.path.join(path, entry)
+
+ # Игнорируем директорию .git/
+ if entry == ".git":
+ continue
+
+ # Проверяем, игнорируется ли файл или директория по правилам .gitignore
+ relative_path = os.path.relpath(full_path, self.project_path)
+ if self._is_ignored(relative_path):
+ continue
+
+ if os.path.isdir(full_path):
+ result += f"{indent}- {entry}/\n"
+ result += self._traverse_directory(full_path, level + 1)
+ else:
+ result += f"{indent}- {entry}\n"
+ return result
+
+ def save_map(self, output_file: str = "react_app_map.txt"):
+ """
+ Сохраняет карту структуры в файл.
+ """
+ map_content = self.generate_map()
+ with open(output_file, "w") as f:
+ f.write(map_content)
+ log(f"Project map saved to {output_file}")
+
+ def _load_gitignore(self) -> list:
+ """
+ Загружает правила из .gitignore, если файл существует.
+ """
+ gitignore_path = os.path.join(self.project_path, ".gitignore")
+ rules = []
+ if os.path.exists(gitignore_path):
+ with open(gitignore_path, "r") as f:
+ for line in f:
+ line = line.strip()
+ if line and not line.startswith("#"): # Игнорируем комментарии и пустые строки
+ rules.append(line)
+ return rules
+
+ def _is_ignored(self, path: str) -> bool:
+ """
+ Проверяет, игнорируется ли файл или директория по правилам .gitignore,
+ включая поддержку сложных правил (например, **/logs/*.log).
+ """
+ # Преобразуем правила .gitignore в PathSpec
+ spec = PathSpec.from_lines(GitWildMatchPattern, self.gitignore_rules)
+
+ # Проверяем, соответствует ли путь правилам
+ return spec.match_file(path)
diff --git a/ReactDev/examples/instructions.md b/ReactDev/examples/instructions.md
new file mode 100644
index 0000000..b1acf9a
--- /dev/null
+++ b/ReactDev/examples/instructions.md
@@ -0,0 +1,9 @@
+1. Компоненты должны быть функциональными и писаться в формате
+```tsx
+function Component({a}:{a:type}){
+ // ...
+}
+```
+2. Функции должны быть написаны в TypeScript.
+3. Используйте современные практики React (например, хуки).
+4. При создании новых компонентов добавьте комментарии.
\ No newline at end of file
diff --git a/ReactDev/utils/file_utils.py b/ReactDev/utils/file_utils.py
new file mode 100644
index 0000000..0e10a0c
--- /dev/null
+++ b/ReactDev/utils/file_utils.py
@@ -0,0 +1,21 @@
+import os
+
+def read_file(file_path: str) -> str:
+ """
+ Читает содержимое файла.
+ """
+ with open(file_path, "r") as f:
+ return f.read()
+
+def write_file(file_path: str, content: str):
+ """
+ Записывает содержимое в файл.
+ """
+ with open(file_path, "w", encoding="utf-8") as f:
+ f.write(content)
+
+def create_directory(path: str):
+ """
+ Создает директорию, если она не существует.
+ """
+ os.makedirs(path, exist_ok=True)
\ No newline at end of file
diff --git a/ReactDev/utils/logger.py b/ReactDev/utils/logger.py
new file mode 100644
index 0000000..36ff2cd
--- /dev/null
+++ b/ReactDev/utils/logger.py
@@ -0,0 +1,13 @@
+import sys
+
+def log(message: str, level: str = "info"):
+ """
+ Логирует сообщения в консоль.
+ """
+ levels = {
+ "info": "[INFO]",
+ "warning": "[WARNING]",
+ "error": "[ERROR]",
+ }
+ prefix = levels.get(level, "[UNKNOWN]")
+ print(f"{prefix} {message}", file=sys.stderr if level == "error" else sys.stdout)
\ No newline at end of file
diff --git a/ReactDev/utils/prompt_utils.py b/ReactDev/utils/prompt_utils.py
new file mode 100644
index 0000000..e69de29
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..72d0c33
--- /dev/null
+++ b/main.py
@@ -0,0 +1,10 @@
+# This is a sample Python script.
+import ReactDev
+
+# Press Shift+F10 to execute it or replace it with your code.
+# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
+
+
+if __name__ == '__main__':
+ ReactDev.run_workflow()
+
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..58856f1
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+requests~=2.32.3
+esprima~=4.0.1
+pathspec~=0.12.1
+openai~=1.82.1
\ No newline at end of file