Files
elmer/AGENTS.md
T

281 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/<mac>` | Профиль скорости 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