diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..d73e544 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,280 @@ +# elmAI — полное описание проекта для AI-агентов + +> Последнее обновление: 2026-07-10 | Версия app: 1.18.0-dev | Версия raw: 0.4.1-dev + +--- + +## 1. ЧТО ЭТО + +elmAI — OBD2-диагностика автомобиля через ELM327-адаптер + LLM (DeepSeek). + +Телефон подключается к ELM327 по Bluetooth, собирает данные с ЭБУ, отправляет на сервер, сервер анализирует через LLM и возвращает диагноз. + +--- + +## 2. РЕПОЗИТОРИИ + +| Репо | URL | Ветка | Что внутри | +|------|-----|-------|-----------| +| **Сервер** | `gitea.services.ngcloud.ru/Nail/elmer` | `dynamic-tests` | Python Flask + elmAI бэкенд | +| **Android** | `github.com/Repinoid/elmer-android` | `opus-fixes` | Kotlin Android-приложение | + +**ВАЖНО**: Android-репо лежит ВНУТРИ серверного: `/home/naeel/elmer/android/`. Это отдельный git-репо со своим remote. Коммитить и пушить надо ИЗНУТРИ `android/`. + +--- + +## 3. СЕРВЕР (obdai.ru, 5.172.178.213) + +``` +elmer/ +├── api/ # Flask API +│ ├── routes.py # Основные эндпоинты (script, upload, chat, probe, sessions) +│ ├── raw_elm.py # Командная очередь для raw-реле (SQLite table command_queue) +│ ├── db.py # SQLite (sessions, device_profiles, command_queue) +│ ├── scripts.py # Сборка диагностических скриптов L0/L1/L2 + dynamic +│ ├── parser.py # Парсинг ответов ELM327 (PID, DTC, VIN) +│ ├── dtc.py # Эндпоинты DTC +│ ├── ping.py # Эндпоинты ping/ping-llm +│ └── config.py # Загрузка config.yaml +├── brain/ # LLM-клиент +│ ├── client.py # Diagnoser — HTTP к DeepSeek +│ └── prompts.py # Промпты для диагностики +├── obd/ # ELM327 протокол (Python) +│ ├── protocol.py # Стейт-машина AndrOBD (ElmProt.java) +│ ├── connection.py, commands.py, classifier.py, probe.py, state.py, timing.py +├── web/ # Flask web +│ ├── app.py # Точка входа, регистрация blueprints +│ ├── templates/index.html # Страница загрузки APK +│ └── static/ # APK-файлы +├── doc/ # ВСЯ документация +├── config.yaml # API-ключи, порты +└── deploy.sh # Скрипт деплоя +``` + +**Стек**: Python 3, Flask, gunicorn (4 воркера, порт 8000), nginx (:443 → :8000), SQLite. + +**Сервис**: `sudo systemctl restart elmer` + +--- + +## 4. ANDROID + +### 4.1. Основное приложение (`app/`) — прямая диагностика + +**Пакет**: `ru.elmer.client` | **Версия**: 1.18.0-dev (versionCode 38) + +``` +app/src/main/java/ru/elmer/client/ +├── Config.kt # Константы: HOST, SCRIPT_URL, defaultScript(), client() +├── db/SessionDb.kt # SQLite: sessions, responses +├── elm/ +│ ├── ElmProtocol.kt # Стейт-машина AndrOBD (1:1 с ElmProt.java) +│ ├── ElmChecker.kt # Проверка ELM: checkDevice(), checkEcu(), scanDtc(), sendRaw() +│ └── ObdDecoder.kt # Декодер PID/DTC/VIN (object-синглтон) +├── script/ +│ └── DynamicCollector.kt # Циклический опрос PID с интервалом +├── server/ +│ └── ServerClient.kt # HTTP к серверу (OkHttp): ping, pingLlm, chat, getSessions, uploadSession, downloadScript +└── ui/ + └── MainActivity.kt # UI: индикаторы, кнопка-трансформер, чат, диагностика, динамический тест +``` + +**8 классов**. Зависимости: OkHttp 4.12.0, AndroidX, org.json. БЕЗ Room, Coroutines, DI. + +**Поток диагностики**: MainActivity → ElmChecker → ElmProtocol → команды → ObdDecoder → SessionDb → ServerClient.uploadSession() → ответ от LLM. + +### 4.2. Raw-реле (`raw/`) — ретранслятор команд + +**Пакет**: `ru.elmer.raw` | **Версия**: 0.4.1-dev (versionCode 18) + +``` +raw/src/main/java/ru/elmer/raw/ +├── ElmProtocol.kt # 1:1 копия app/ElmProtocol.kt +├── ElmActor.kt # Single-thread executor вокруг ElmProtocol +├── RawRelayService.kt # Foreground-сервис: BT→init→поллинг команд→ответ +├── RelayClient.kt # HTTP к /api/v1/elm/raw/* (OkHttp, БЕЗ X-Api-Key) +└── MainActivity.kt # Минимальный UI (выбор BT, статус, счётчики) +``` + +**5 классов**. Отдельный APK (`applicationId: ru.elmer.raw`). + +**Поток**: RawRelayService → connectBt → ElmProtocol.init() → hello → цикл: pollCommand → sendCommand → postResponse. + +**Назначение**: тупой ретранслятор. Сервер диктует команды, телефон передаёт в ELM и возвращает ответы. Используется для интерактивной диагностики через Copilot и тестов 3 мин / 5 мин. + +--- + +## 5. ANDROID — ЧТО СДЕЛАНО (рефакторинг 2026-07-10) + +Ветка `opus-fixes`, 8 коммитов: + +1. **Config.kt** — единый источник хоста (`https://obdai.ru`), замена всех хардкодов +2. **default_script.json** → `assets/`, DEFAULT_SCRIPT из кода удалён +3. **ServerClient** — добавлены `chat()` и `getSessions()`, весь HTTP через OkHttp + X-Api-Key +4. **HttpURLConnection** выпилен из MainActivity +5. **ElmChecker.sendRaw()** — инкапсуляция ElmProtocol, `getElm()` удалён +6. **FQN → import** — все полные имена заменены на нормальные import'ы +7. **Удалён мёртвый код**: ScriptRunnerService, ScriptEngine, UploadProgress + FOREGROUND_SERVICE permissions + +**Результат**: 8 классов (было 10), 0 HttpURLConnection, 0 FQN, 0 getElm(), 0 obdai.ru вне Config, весь HTTP аутентифицирован. + +--- + +## 6. ANDROID — ЧТО НЕ СДЕЛАНО (TODO) + +### app/ +- Разбить MainActivity (~750 строк) — вынести логику из UI +- Разбить ElmChecker (372 строки) — отделить BT от ELM-команд +- v1.5 клоны: деградация после 10-12 команд (ограничение железа) + +### raw/ +- **deviceId** генерится заново при каждом создании RelayClient — сохранить в SharedPreferences +- **Нет аутентификации** — BuildConfig.API_KEY есть, но RelayClient его не шлёт +- **Нет retry** при ошибках HTTP +- **SERVER_URL** захардкожен в build.gradle.kts и дублируется в Intent extra +- **drainInput() в write()** — потенциальный сдвиг буфера (Неудача #5 из failures-journal.md) + +### Сервер +- Script Engine для режимов «3 мин на месте» / «5 мин в движении» — НЕ РЕАЛИЗОВАН +- Дублирование: routes.py и script_endpoint.py (script_endpoint.py — мёртвый) + +--- + +## 7. РЕЖИМЫ ДИАГНОСТИКИ + +### Режим 1: Прямая диагностика (app/) +Однократный сбор данных: скрипт → батч ответов → сервер → LLM → диагноз. + +### Режим 2: Динамический тест (app/) +Циклический опрос PID. Кнопка СТАРТ/СТОП. Сервер подбирает тайминги через `/api/v1/test/next`. + +### Режим 3: Raw-реле (raw/) +Сервер управляет потоком команд. Телефон — тупой ретранслятор. + +### Режим 4: Прогрев на месте (raw/, 3 минуты) +3 PID (RPM, темп, дроссель) каждые 2 секунды × 90 циклов = 270 запросов. Оценка прогрева, холостых, реакции на газ. + +### Режим 5: В движении (raw/, 5 минут) +Те же 3 PID каждые 2 секунды × 150 циклов = 450 запросов. Нагрузочный тест, динамика разгона. + +*Режимы 4 и 5 требует реализации Script Engine на сервере.* + +--- + +## 8. API ЭНДПОИНТЫ + +### Основные (app/) + +| Метод | Путь | Назначение | +|-------|------|-----------| +| GET | `/api/v1/ping` | Проверка сервера | +| GET | `/api/v1/ping-llm` | Проверка LLM | +| GET | `/api/v1/script?mode=test` | Скрипт диагностики | +| POST | `/api/v1/session/upload` | Загрузка батча + LLM-анализ | +| POST | `/api/v1/chat` | Чат с LLM | +| GET | `/api/v1/sessions` | Список сессий | +| POST | `/api/v1/test/next` | Следующий шаг динамического теста | +| GET/PUT | `/api/v1/elm/profile/` | Профиль скорости ELM | + +### Raw-реле (raw/) + +| Метод | Путь | Назначение | +|-------|------|-----------| +| POST | `/api/v1/elm/raw/hello` | Android: «я готов» (чистит старые команды) | +| POST | `/api/v1/elm/raw/cmd` | Copilot/сервер: поставить команду в очередь | +| GET | `/api/v1/elm/raw/cmd?device_id=X` | Android: забрать pending команду | +| POST | `/api/v1/elm/raw/response` | Android: вернуть ответ | +| GET | `/api/v1/elm/raw/response?device_id=X&seq=N` | Copilot: прочитать ответ | +| GET | `/api/v1/elm/raw/status` | Статус устройства | + +--- + +## 9. ДЕПЛОЙ + +### 9.1. Сервер + +```bash +cd /home/naeel/elmer +git add -A && git commit -m "..." && git push origin dynamic-tests + +ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 " + cd /opt/elmer && git checkout dynamic-tests && git pull origin dynamic-tests + pip install -r requirements.txt + sudo systemctl restart elmer +" +``` + +### 9.2. Android APK (app) + +```bash +# 1. Bump версии в app/build.gradle.kts (versionCode и versionName) +cd /home/naeel/elmer/android +sed -i 's/versionCode = XX/versionCode = YY/' app/build.gradle.kts +sed -i 's/versionName = "X.Y.Z-dev"/versionName = "X.Y+1.Z-dev"/' app/build.gradle.kts + +# 2. Закоммитить + запушить +git add -A && git commit -m "bump vX.Y+1.Z-dev" && git push origin opus-fixes + +# 3. Залить исходники на сервер и собрать APK +cd /home/naeel/elmer +tar czf /tmp/android-src.tar.gz --exclude='.git' --exclude='build' --exclude='.gradle' android/ +scp -i ~/.ssh/naeel_vm_id_ed25519 /tmp/android-src.tar.gz naeel@5.172.178.213:/tmp/ + +ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 " + rm -rf /opt/elmer/android && tar xzf /tmp/android-src.tar.gz -C /opt/elmer/ + cd /opt/elmer/android && gradle wrapper --gradle-version 8.7 + export ANDROID_SDK_ROOT=\$HOME/android-sdk + ./gradlew :app:clean :app:assembleDebug + cp app/build/outputs/apk/debug/app-debug.apk /opt/elmer/web/static/ +" +# 4. Обновить версию в /opt/elmer/web/templates/index.html и /opt/elmer/templates/index.html +``` + +### 9.3. Raw APK + +```bash +# Аналогично app, но: +# - bump версии в raw/build.gradle.kts +# - сборка: ./gradlew :raw:assembleDebug +# - копия: cp raw/build/outputs/apk/debug/raw-debug.apk /opt/elmer/web/static/elm-raw-v022.apk +``` + +--- + +## 10. ПРАВИЛА (НЕ НАРУШАТЬ) + +1. **НИЧЕГО не делать без прямого указания пользователя.** Даже если видишь проблему — только сказать. +2. **На вопрос — только ответ.** Не продолжать «а ещё могу...», не предлагать помощь. +3. **После выполнения команды — сказать «готово» и ЖДАТЬ.** +4. **Коммит + push после КАЖДОЙ правки.** Один коммит = одна правка. Формат: `fix:`, `feat:`, `refactor:`, `bump:`, `docs:`, `style:`, `chore:`. +5. **При деплое — всегда bump версии.** Инкрементировать патч (Z в X.Y.Z-dev). +6. **ELM327 — только как AndrOBD (ElmProt.java).** Никакой самодеятельности в протоколе. Init: ATSP0→ATAT1→ATS0→ATL0→ATE0. Никакого drainInput() перед write(). +7. **Не материться.** Пользователь матерится — ты нет. +8. **Не гадать.** Если не уверен — проверить факты чтением кода. +9. **Код правит ТОЛЬКО пользователь или Copilot по команде.** Не исполнять советы Opus по ELM-командам — Opus специалист по архитектуре кода, а не по ELM327. + +--- + +## 11. КЛЮЧЕВЫЕ ДОКУМЕНТЫ + +| Файл | Содержание | +|------|-----------| +| `AGENTS.md` | Этот файл — полное описание проекта | +| `doc/architecture.md` | Архитектура сервера и Android | +| `doc/diagnostic-logic.md` | 5 режимов диагностики | +| `doc/failures-journal.md` | 12 провалов при разработке raw-реле | +| `doc/SETUP.md` | Настройка окружения | +| `STRUCTURE.md` | Полное дерево файлов | +| `resume.txt` | Краткое резюме для нового чата | +| `.github/copilot-instructions.md` | Правила для Copilot | +| `android/doc/opus-arch-questions-2026-07-10.md` | Вопросы Opus по архитектуре | +| `android/doc/opus-refactor-plan-2026-07-10.md` | План рефакторинга от Opus | + +--- + +## 12. КОНТАКТЫ / ДОСТУП + +- **Сервер**: 5.172.178.213, SSH: `naeel@5.172.178.213`, ключ: `~/.ssh/naeel_vm_id_ed25519` +- **Домен**: obdai.ru (SSL через certbot) +- **Gitea**: gitea.services.ngcloud.ru/Nail/elmer +- **GitHub**: github.com/Repinoid/elmer-android