diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..b957e25 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,124 @@ +CHANGELOG +========= + +Версия 2.0.0 (2025-01-19) +========================= + +КРУПНОЕ ОБНОВЛЕНИЕ: Полная реструктуризация архитектуры и добавление веб-интерфейса + +## 🚀 НОВЫЕ ВОЗМОЖНОСТИ + +### Веб-интерфейс +- ✨ Добавлен полноценный веб-сервер для управления результатами +- 🌐 Веб-интерфейс доступен по адресу http://localhost:8080 (по умолчанию) +- 📊 Страница просмотра результатов с форматированием и подсветкой синтаксиса +- 📝 Страница истории запросов с возможностью удаления +- ⚙️ Страница управления промптами с полным CRUD функционалом + +### Управление промптами +- 🔧 Полная система управления системными промптами через веб-интерфейс +- 🌍 Поддержка многоязычности (английский/русский) с переключением языка +- 📝 Редактирование, добавление и удаление промптов через веб-интерфейс +- 🔄 Кнопки восстановления промптов к значениям по умолчанию +- 📋 Двухвкладочный интерфейс: системные промпты (1-5) и промпты подробности (v/vv/vvv) + +### Улучшенная система промптов +- 📁 Централизованное хранение промптов в файле sys_prompts +- 🏗️ Встроенные промпты загружаются из YAML файла (builtin_prompts.yaml) +- 🔍 Автоматическое определение встроенных промптов +- 🌐 Многоязычные промпты с поддержкой английского и русского языков +- 🔄 Автоматическая инициализация sys_prompts при первом запуске CLI + +### Новые CLI команды +- 📜 `lcg history` - просмотр истории запросов +- 📜 `lcg history clear` - очистка истории +- 📜 `lcg history delete ` - удаление записи из истории +- 📝 `lcg prompts list` - список всех промптов +- 📝 `lcg prompts list --full` - полный вывод содержимого промптов +- 📝 `lcg prompts add` - добавление нового промпта +- 📝 `lcg prompts edit ` - редактирование промпта +- 📝 `lcg prompts delete ` - удаление промпта + +### Расширенная функциональность +- 🔍 Флаг --debug для отображения параметров запросов и промптов +- 📊 Улучшенное отображение результатов с подсветкой синтаксиса +- 🎨 Обновленный дизайн веб-интерфейса с современным UI +- 📱 Адаптивный дизайн для различных размеров экрана + +## 🏗️ АРХИТЕКТУРНЫЕ ИЗМЕНЕНИЯ + +### Новая структура проекта +- 📁 cmd/ - модули команд (explain.go, history.go, serve.go) +- 📁 config/ - централизованная конфигурация +- 📁 gpt/ - логика работы с промптами и LLM +- 📁 reader/ - модуль чтения файлов +- 📁 shell-code/ - скрипты сборки и развертывания + +### Централизованная конфигурация +- ⚙️ config/config.go - единая точка конфигурации +- 🔧 Поддержка переменных окружения для всех настроек +- 📝 Автоматическое создание конфигурационных файлов + +### Встроенные промпты +- 📄 builtin_prompts.yaml - YAML файл с встроенными промптами +- 🔧 builtin_prompts.go - логика работы с встроенными промптами +- 🌐 Поддержка многоязычности на уровне YAML + +## 🐛 ИСПРАВЛЕНИЯ + +- 🔧 Исправлена проблема с регистронезависимым поиском в истории +- 🎨 Улучшена цветовая схема веб-интерфейса (менее яркие цвета) +- 🔘 Стандартизированы размеры и цвета кнопок навигации +- 🌍 Исправлена логика определения языка в веб-интерфейсе +- 🔍 Исправлена логика определения встроенных промптов при смене языка + +## 📋 ОБРАТНАЯ СОВМЕСТИМОСТЬ + +- ✅ Все существующие CLI команды сохранены +- ✅ Поддержка всех переменных окружения из v1.x.x +- ✅ Автоматическая миграция существующих конфигураций +- ✅ Сохранена совместимость с существующими API + +## 🔧 ТЕХНИЧЕСКИЕ УЛУЧШЕНИЯ + +### Производительность +- ⚡ Оптимизирована загрузка промптов +- 🚀 Улучшена скорость работы веб-интерфейса +- 💾 Эффективное кэширование промптов + +### Безопасность +- 🔒 Валидация входных данных в веб-интерфейсе +- 🛡️ Защита от XSS атак +- 🔐 Безопасная обработка файлов + +### Код +- 🧹 Рефакторинг архитектуры для лучшей поддерживаемости +- 📚 Улучшенная документация кода +- 🧪 Добавлены тесты для критических компонентов + +## 📦 ЗАВИСИМОСТИ + +### Новые зависимости +- github.com/urfave/cli/v2 - CLI фреймворк +- gopkg.in/yaml.v3 - работа с YAML файлами +- html/template - шаблонизация веб-страниц + +### Обновленные зависимости +- Обновлены все существующие зависимости до последних версий + +## 🚀 МИГРАЦИЯ С v1.x.x + +1. **Автоматическая миграция**: При первом запуске v2.0.0 автоматически создастся файл sys_prompts с встроенными промптами +2. **Сохранение настроек**: Все переменные окружения и настройки сохраняются +3. **Новые возможности**: Доступ к веб-интерфейсу через `lcg serve-result` +4. **Управление промптами**: Используйте `lcg prompts list` для просмотра всех промптов + +## 📖 ДОКУМЕНТАЦИЯ + +- 📚 Обновлен USAGE_GUIDE.md с описанием новых команд +- 📋 Добавлен API_CONTRACT.md для веб-интерфейса +- 🔧 Обновлен README.md с инструкциями по использованию + +--- + +**Примечание**: Версия 2.0.0 представляет собой кардинальное обновление с полной реструктуризацией архитектуры. Рекомендуется ознакомиться с новыми возможностями веб-интерфейса и системой управления промптами. diff --git a/README.md b/README.md index 2ee0461..56e514c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Generate Linux commands from natural language. Supports Ollama and Proxy backend Build from source: ```bash -git clone --depth 1 https://github.com/Direct-Dev-Ru/go-lcg.git ~/.linux-command-gpt +git clone --depth 1 https://github.com/Direct-Dev-Ru/linux-command-gpt.git ~/.linux-command-gpt cd ~/.linux-command-gpt go build -o lcg @@ -37,10 +37,20 @@ Clipboard support requires `xclip` or `xsel`. ## Environment -- `LCG_PROVIDER` (ollama|proxy), `LCG_HOST`, `LCG_MODEL`, `LCG_PROMPT` -- `LCG_TIMEOUT` (default 120), `LCG_RESULT_FOLDER` (default ./gpt_results) -- `LCG_RESULT_HISTORY` (default $(LCG_RESULT_FOLDER)/lcg_history.json) -- `LCG_JWT_TOKEN` (for proxy) +- `LCG_PROVIDER` (default `ollama`) — provider type: `ollama` or `proxy` +- `LCG_HOST` (default `http://192.168.87.108:11434/`) — base API URL +- `LCG_MODEL` (default `hf.co/yandex/YandexGPT-5-Lite-8B-instruct-GGUF:Q4_K_M`) +- `LCG_PROMPT` — default system prompt content +- `LCG_PROXY_URL` (default `/api/v1/protected/sberchat/chat`) — proxy chat endpoint +- `LCG_COMPLETIONS_PATH` (default `api/chat`) — Ollama chat endpoint (relative) +- `LCG_TIMEOUT` (default `300`) — request timeout in seconds +- `LCG_RESULT_FOLDER` (default `~/.config/lcg/gpt_results`) — folder for saved results +- `LCG_RESULT_HISTORY` (default `$(LCG_RESULT_FOLDER)/lcg_history.json`) — JSON history path +- `LCG_PROMPT_FOLDER` (default `~/.config/lcg/gpt_sys_prompts`) — folder for system prompts +- `LCG_PROMPT_ID` (default `1`) — default system prompt ID +- `LCG_JWT_TOKEN` — JWT token for proxy provider +- `LCG_NO_HISTORY` — if `1`/`true`, disables history writes for the process +- `LCG_SERVER_PORT` (default `8080`), `LCG_SERVER_HOST` (default `localhost`) — HTTP server settings ## Flags @@ -48,6 +58,8 @@ Clipboard support requires `xclip` or `xsel`. - `--sys, -s` system prompt content or ID - `--prompt-id, --pid` choose built-in prompt (1–5) - `--timeout, -t` request timeout (sec) +- `--no-history, --nh` disable writing/updating JSON history for this run +- `--debug, -d` show debug information (request parameters and prompts) - `--version, -v` print version; `--help, -h` help ## Commands @@ -60,10 +72,11 @@ Clipboard support requires `xclip` or `xsel`. - `history list` — list history from JSON - `history view ` — view by index - `history delete ` — delete by index (re-numbering) +- `serve-result` — start HTTP server to browse saved results (`--port`, `--host`) ## Saving results -Files are saved to `LCG_RESULT_FOLDER`. +Files are saved to `LCG_RESULT_FOLDER` (default `~/.config/lcg/gpt_results`). - Command result: `gpt_request__YYYY-MM-DD_HH-MM-SS.md` - `# ` — H1 with original request (trimmed to 120 chars: first 116 + `...`) diff --git a/USAGE_GUIDE.md b/USAGE_GUIDE.md index 5be1950..f2ec67f 100644 --- a/USAGE_GUIDE.md +++ b/USAGE_GUIDE.md @@ -21,7 +21,7 @@ sudo apt-get install xsel Сборка из исходников: ```bash -git clone --depth 1 https://github.com/asrul10/linux-command-gpt.git ~/.linux-command-gpt +git clone --depth 1 https://github.com/Direct-Dev-Ru/linux-command-gpt.git ~/.linux-command-gpt cd ~/.linux-command-gpt go build -o lcg diff --git a/cmd/history.go b/cmd/history.go index 1c96835..667a92d 100644 --- a/cmd/history.go +++ b/cmd/history.go @@ -54,6 +54,7 @@ func ShowHistory(historyPath string, printColored func(string, string), colorYel for _, h := range items { ts := h.Timestamp.Format("2006-01-02 15:04:05") fmt.Printf("%d. [%s] %s → %s\n", h.Index, ts, h.Command, h.Response) + fmt.Printf("%s\n", "========================================================================================") } } diff --git a/shell-code/pre-release.sh b/shell-code/pre-release.sh index 15c24e6..3aefe80 100644 --- a/shell-code/pre-release.sh +++ b/shell-code/pre-release.sh @@ -2,4 +2,4 @@ go-ansible-vault -i shell-code/build.env -a get -m GITHUB_TOKEN > /tmp/source && source /tmp/source -#GITHUB_TOKEN=$GITHUB_TOKEN python3 shell-code/release.py \ No newline at end of file +GITHUB_TOKEN=$GITHUB_TOKEN python3 shell-code/release.py \ No newline at end of file diff --git a/shell-code/release.py b/shell-code/release.py index d1091d9..49cb52b 100644 --- a/shell-code/release.py +++ b/shell-code/release.py @@ -11,6 +11,8 @@ import requests from pathlib import Path # Цвета для вывода + + class Colors: RED = '\033[0;31m' GREEN = '\033[0;32m' @@ -18,23 +20,29 @@ class Colors: BLUE = '\033[0;34m' NC = '\033[0m' # No Color + def log(message): print(f"{Colors.GREEN}[INFO]{Colors.NC} {message}") + def error(message): print(f"{Colors.RED}[ERROR]{Colors.NC} {message}", file=sys.stderr) + def warn(message): print(f"{Colors.YELLOW}[WARN]{Colors.NC} {message}") + def debug(message): print(f"{Colors.BLUE}[DEBUG]{Colors.NC} {message}") + # Конфигурация REPO = "direct-dev-ru/go-lcg" VERSION_FILE = "VERSION.txt" BINARIES_DIR = "binaries-for-upload" + def check_environment(): """Проверка переменных окружения""" token = os.getenv('GITHUB_TOKEN') @@ -44,39 +52,42 @@ def check_environment(): log(f"GITHUB_TOKEN установлен (длина: {len(token)} символов)") return token + def get_version(): """Получение версии из файла""" version_file = Path(VERSION_FILE) if not version_file.exists(): error(f"Файл {VERSION_FILE} не найден") sys.exit(1) - + version = version_file.read_text().strip() tag = f"lcg.{version}" log(f"Версия: {version}") log(f"Тег: {tag}") return tag + def check_files(): """Проверка файлов для загрузки""" binaries_path = Path(BINARIES_DIR) if not binaries_path.exists(): error(f"Директория {BINARIES_DIR} не найдена") sys.exit(1) - + files = list(binaries_path.glob("*")) files = [f for f in files if f.is_file()] - + if not files: error(f"В директории {BINARIES_DIR} нет файлов") sys.exit(1) - + log(f"Найдено файлов: {len(files)}") for file in files: log(f" - {file.name} ({file.stat().st_size} байт)") - + return files + def create_github_session(token): """Создание сессии для GitHub API""" session = requests.Session() @@ -87,28 +98,30 @@ def create_github_session(token): }) return session + def check_existing_release(session, tag): """Проверка существующего релиза""" log("Проверяем существующий релиз...") url = f"https://api.github.com/repos/{REPO}/releases/tags/{tag}" - + response = session.get(url) if response.status_code == 200: release_data = response.json() - log(f"Реліз {tag} уже существует") + log(f"Релиз с тегом {tag} уже существует") return release_data elif response.status_code == 404: - log(f"Реліз {tag} не найден, создаем новый") + log(f"Релиз с тегом {tag} не найден, создаем новый") return None else: error(f"Ошибка проверки релиза: {response.status_code}") debug(f"Ответ: {response.text}") sys.exit(1) + def create_release(session, tag): """Создание нового релиза""" log(f"Создаем новый релиз {tag}...") - + data = { "tag_name": tag, "name": tag, @@ -116,38 +129,34 @@ def create_release(session, tag): "draft": False, "prerelease": False } - + url = f"https://api.github.com/repos/{REPO}/releases" response = session.post(url, json=data) - + if response.status_code == 201: release_data = response.json() - log("Реліз создан успешно") + log("Релиз с тегом {tag} создан успешно") return release_data else: - error(f"Ошибка создания релиза: {response.status_code}") + error(f"Ошибка создания релиза с тегом {tag}: {response.status_code}") debug(f"Ответ: {response.text}") sys.exit(1) + def upload_file(session, upload_url, file_path): """Загрузка файла в релиз""" filename = file_path.name - log(f"Загружаем: {filename}") - - # Убираем {?name,label} из URL - upload_url = upload_url.replace("{?name,label}", "") - with open(file_path, 'rb') as f: headers = {'Content-Type': 'application/octet-stream'} params = {'name': filename} - + response = session.post( upload_url, data=f, headers=headers, params=params ) - + if response.status_code == 201: log(f"✓ {filename} загружен") return True @@ -156,38 +165,39 @@ def upload_file(session, upload_url, file_path): debug(f"Ответ: {response.text}") return False + def main(): """Основная функция""" log("=== НАЧАЛО РАБОТЫ СКРИПТА ===") - + # Проверки token = check_environment() tag = get_version() files = check_files() - + # Создание сессии session = create_github_session(token) - + # Проверка/создание релиза release = check_existing_release(session, tag) if not release: release = create_release(session, tag) - + # Получение URL для загрузки upload_url = release['upload_url'] log(f"Upload URL: {upload_url}") - + # Загрузка файлов log("=== ЗАГРУЗКА ФАЙЛОВ ===") uploaded = 0 failed = 0 - + for file_path in files: if upload_file(session, upload_url, file_path): uploaded += 1 else: failed += 1 - + # Результат log("=== РЕЗУЛЬТАТ ===") log(f"Успешно загружено: {uploaded}") @@ -195,9 +205,10 @@ def main(): warn(f"Ошибок: {failed}") else: log("Все файлы загружены успешно!") - + log(f"Реліз доступен: https://github.com/{REPO}/releases/tag/{tag}") log("=== СКРИПТ ЗАВЕРШЕН ===") + if __name__ == "__main__": main()